home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / cnetdevice / src / cnetdevice.asm < prev    next >
Assembly Source File  |  2000-05-25  |  122KB  |  4,469 lines

  1. ;---------------------------------------------------------------------------
  2. ;                  PCMCIA ethernet card driver for A600/A1200
  3. ;---------------------------------------------------------------------------
  4. ;
  5. ; HISTORY:
  6. ;
  7. ; 10-4-97  v0.1 - Created by Bruce Abbott (bhabbott@inhb.co.nz)
  8. ;                      *** First Aminet Release ***
  9. ;
  10. ; 29-4-97  v0.2 - Implemented CMD_ONLINE/OFFLINE/FLUSH (for Miami).
  11. ;
  12. ;               - Enabled interrupts during RemoteWrite (no more serial
  13. ;                 port overruns!).
  14. ;
  15. ; 6-5-97   v0.3 - Added a flag so that we won't try to ReleaseCard()
  16. ;                 unless there was a successful OwnCard()!
  17. ;
  18. ; 17-5-97  v0.4 - CMD_CONFIGINTERFACE now overrides the default hardware
  19. ;                 address (for Miami).
  20. ;
  21. ;               - Device now goes offline if the PCMCIA card is removed.
  22. ;
  23. ;               - CMD_ONEVENT implemented.
  24. ;
  25. ;               - Loosened hardware address verification to accept the
  26. ;                 Accton EN2216.
  27. ;
  28. ;               - Unrolled loops to improve data transfer speed. Now
  29. ;                 about 20% faster on an unexpanded A600.
  30. ;
  31. ;               - Hack to fix problem with missed interrupts. Now we
  32. ;                 clear the Gayle interrupt bits instead of letting
  33. ;                 card.resource do it for us.
  34. ;
  35. ;                        *** Second Aminet Release ***
  36. ;
  37. ; 29-7-97  v0.5 - Accepts 802.3 packets (untested).
  38. ;
  39. ;               - Sets BROADCAST bit in io_flags when appropriate.
  40. ;
  41. ;               - Now examines PCMCIA attribute memory to determine
  42. ;                 value to write into Card Configuration Register.
  43. ;
  44. ;               - If attribute memory not found, tries to open the file
  45. ;                 "s:cnetdev.config" to get Card Configuration Register
  46. ;                 offset, Configuration ID, and ROM Station Address.
  47. ;
  48. ;                        *** Third Aminet Release ***
  49. ;
  50. ;22-12-97 v0.6 - I/O addressing now supports 64KByte range (was 1KB).
  51. ;
  52. ;              - Tighter data transfer loops, slightly faster on '030.
  53. ;
  54. ;              - Accepts all Card Configuration Register address sizes.
  55. ;
  56. ;              - Removed cnet.config stuff (replaced with hardware mod).
  57. ;
  58. ;              - Now cards are hot-swappable.
  59. ;
  60. ;              - Un-supported commands now return S2ERR_NOT_SUPPORTED.
  61. ;
  62. ;                        *** 4th Aminet Release ***
  63. ;
  64. ;21-4-98 v0.7  - fixed harmless bug in init_nic - remote DMA timeout test
  65. ;                could not fail!
  66. ;
  67. ;              - Now remembers copytobuf/copyfrombuf tags for each opener.
  68. ;                Allows simultaneous use of eg. AmiTCP and Envoy.
  69. ;
  70. ;              - OnEvent types ONLINE and OFFLINE now return immediately
  71. ;                if the device is already in the wanted state.
  72. ;
  73. ;                        *** 5th Aminet Release ***
  74. ;
  75. ;17-12-98 v0.8 - fixed bug in OnEvent: was using wrong register to test
  76. ;                ONLINE flag.
  77. ;
  78. ; 1-6-99 v0.9  - Added support for multicasting, statistics, orphan packets,
  79. ;                exclusive and promiscuous modes.
  80. ;
  81. ;                        *** 6th Aminet Release ***
  82. ;
  83. ; 5-7-99 v1.0  - Fixed bug in readpacket: MCAST flag was also set when packet
  84. ;                was BCAST.
  85. ;
  86. ;                        *** 7th Aminet Release ***
  87. ;
  88. ; 7-7-99 v1.1  - Fixed bug: delmulticast always failed due to bad testing
  89. ;                for multicast address match.
  90. ;
  91. ;              - Fixed bug: readpacket was getting incorrect src and dst
  92. ;                addresses (A4 was pointing to prhdr instead of etherhdr).
  93. ;
  94. ;              - Included put_multi in init_nic (need to reload multicast
  95. ;                bits if card is removed and re-inserted)
  96. ;
  97. ;              - Added 4 to rx ios2_datalength in raw mode. Shapeshifter
  98. ;                seems to need this (why?)
  99. ;
  100. ;                        *** 8th Aminet release ***
  101. ;
  102. ;7-5-00 v1.2b1 - Since there has been almost ten months without an update,
  103. ;                I, Harry Sintonen <sintonen@iki.fi>, decided to have a go.
  104. ;
  105. ;              - Reformatted this source code: Now registers are always in
  106. ;                lowercase, for better readability.
  107. ;
  108. ;              - Added MN_LENGTH check for OpenDevice() (S2R3 and NSD require
  109. ;                this).
  110. ;
  111. ;              - Fixed a bug: If TAG_IGNORE, TAG_MORE or TAG_SKIP were used
  112. ;                in the IOSana2Req's taglist Open_Unit got really confused,
  113. ;                throwing enforcer hits, and in a worst case, crashing the
  114. ;                machine. Now uses utility.library GetTagData().
  115. ;
  116. ;              - Optimized dbf loops to subq + branch for better 020+
  117. ;                performance. Made several other miscallenous optimizations
  118. ;                thruout the code.
  119. ;
  120. ;              - More bugs fixed: DoEvent examined dd_eventlist before
  121. ;                Disable(). devcmd_addmulticast and devcmd_delmulticast
  122. ;                didn't lock the list, devcmd_delmulticast called Enable()
  123. ;                without Disable() when no multicast was found. Protected
  124. ;                dd_multicasts list with semaphore. dd_bufmanlist was
  125. ;                accessed without list arbitration, added Disable()/Enable()
  126. ;                pair when needed.
  127. ;
  128. ;              - Added support for S2_PacketFilter tag. Speedup: replaced
  129. ;                several list related calls with macros.
  130. ;
  131. ;              - Rewrote CMD_READ handling: Added proper Multiple Protocol
  132. ;                Stack Support, it was really broken before. Basically this
  133. ;                means that each opener gets all the packets necessary. If a
  134. ;                packet comes in that fills a request for more than one
  135. ;                opener of the device, *all* of them will get a copy of the
  136. ;                packet. Of course each caller can ask RAW or non-RAW version
  137. ;                of the packet. cnet.device fully comply to S2R2 now!
  138. ;
  139. ;              - Since complies to S2R2, added NewStyleDevice (NSD) support.
  140. ;                Also added S2R3 S2_DMACopyFromBuff32 tag support, however
  141. ;                this feature is currently disabled. ***
  142. ;                S2_DMACopyToBuff32 would only pay off if: 1) there is only
  143. ;                one caller for this packet, and 2) there is no packet filter
  144. ;                for this caller.
  145. ;
  146. ;              - More speedups: Replaced exec Disable() and Enable() calls
  147. ;                with macros. Yet more list related calls replaced with
  148. ;                macros.
  149. ;
  150. ;              - Yet more bugs fixed: CMD_FLUSH didn't abort S2_READORPHANs.
  151. ;                CMD_OFFLINE didn't abort pending CMD_READs, S2_READORPHANs
  152. ;                and CMD_WRITEs. CMD_READ and S2_READORPHAN didn't check for
  153. ;                card being online. S2_ONEVENT didn't check if it knows the
  154. ;                event condition(s) specified, instead requests for unknown
  155. ;                event(s) would never have got returned. Also S2_ONEVENT
  156. ;                returned the ioreq even if it was queued. S2_CONFIGINTERFACE
  157. ;                worked more than once, it *must* only work once.
  158. ;                OpenDevice() incorrectly required S2_CopyFromBuff and
  159. ;                S2_CopyToBuff tags to be present.
  160. ;
  161. ;              - Yet more speedups: DoEvent uses global cached device
  162. ;                pointer.
  163. ;
  164. ;              - init_card and init_nic fire S2EVENT_ERROR|S2EVENT_HARDWARE
  165. ;                event if something goes wrong. Trying to send too big of a
  166. ;                packet trigger S2EVENT_TX. If packet gets dropped during
  167. ;                receive S2EVENT_ERROR|S2EVENT_RX event is triggered. If
  168. ;                copyfrombuf while transmitting fails S2EVENT_TX|S2EVENT_BUFF
  169. ;                event is triggered, and similarily if copytobuf while
  170. ;                receiving fails S2EVENT_RX|S2EVENT_BUFF event is triggered.
  171. ;
  172. ;              - Extensively debugged for 18+6 hours to make 1st early beta
  173. ;                possible...
  174. ;
  175. ;              - Currently at least following should work: CMD_READ,
  176. ;                CMD_WRITE, CMD_FLUSH, S2_DEVICEQUERY, S2_GETSTATIONADDRESS,
  177. ;                S2_CONFIGINTERFACE, S2_ADDMULTICASTADDRESS,
  178. ;                S2_DELMULTICASTADDRESS, S2_MULTICAST, S2_BROADCAST,
  179. ;                S2_TRACKTYPE, S2_UNTRACKTYPE, S2_GETTYPESTATS,
  180. ;                S2_GETSPECIALSTATS, S2_GETGLOBALSTATS, S2_ONEVENT,
  181. ;                S2_READORPHAN, S2_ONLINE, S2_OFFLINE and NSCMD_DEVICEQUERY.
  182. ;
  183. ;              - Tested with sanamon, sanautil, miamidx and genesis.
  184. ;
  185. ;                        *** internal 1.2beta1 release ***
  186. ;
  187. ;9-5-00 v1.2b2 - initRoutine trashed a6 by leaving execbase in it, but since
  188. ;                it *is* execbase originally it was harmless. Silly. :)
  189. ;
  190. ;              - Misc minor changes here and there.
  191. ;
  192. ;              - Added device expunge. esp. cool for debugging, no more those
  193. ;                damn annoying reboots. Also someone might want to quit
  194. ;                protocol stack, avail flush, and use some other card without
  195. ;                the need to reboot. Now DDF_CONFIGURED is reset only on
  196. ;                device flush, this means that pulling the card out doesn't
  197. ;                cut the connection anymore, and you can continue by plugging
  198. ;                the card back in. v1.2b1 didn't allow this hot swapping
  199. ;                trick, but v1.1 did.
  200. ;
  201. ;              - Bugfixes: initRoutine crashed if utility.library v36 failed
  202. ;                to open. Partially successful OpenDevice ate some resources,
  203. ;                now it should be able to back out in all cases. S2_OFFLINE
  204. ;                should, I quote: "Aborts all pending reads and writes with
  205. ;                ios2_Error set to S2ERR_OUTOFSERVICE.". However this makes
  206. ;                MiamiDx die a horrible death. Took me 10 hours to find why.
  207. ;                Damn it! Disabled IO aborting and now it works. D'oh!
  208. ;
  209. ;              - Speedup: Implemented turbo RemoteRead & RemoteWrite loops,
  210. ;                they use longword access to 16bit register. Don't worry,
  211. ;                this works, but honestly I have no clue why. Enabled DMA for
  212. ;                both regular and raw CMD_WRITEs. At least MiamiDx support
  213. ;                S2_DMACopyFromBuff32. Moving 30mb mpg between my amiga and
  214. ;                laptop result about 450kb/s upload and 500kb/s download
  215. ;                speed. v1.1 and the same environment gave about 420kb/s
  216. ;                upload and 450kb/s download speed.
  217. ;                (ftp client AmFTP 1.92, ftpd Version 6.2/OpenBSD/Linux-0.10)
  218. ;
  219. ;              - Made Makefile generate 68000 version of the device. No real
  220. ;                differences yet tho. this version is untested!
  221. ;
  222. ;                        *** internal 1.2beta2 release ***
  223. ;
  224. ;16-5-00 v1.2b3  Got a report that v1.2b2 is actually slower than v1.2b1.
  225. ;                Well I wrote a simple AmigaE program that I can use to
  226. ;                benchmark cnet.device CMD_WRITE. Turned out that turboio
  227. ;                transfer ~679kb/s and non-turboio 697kb/s without DMA
  228. ;                transfer, in DMA mode the same figures are 694kb/s vs. 713
  229. ;                kb/s. Oh dear, this is it, I disabled turboio. :) Thanks go
  230. ;                to Tundrah for the tip. BTW: it seems we're finally getting
  231. ;                there, he get ~770kb/s real life transfer speed using FTP
  232. ;                (Apollo ethernet, 060 @ 66). Not bad. Btw benchmarking
  233. ;                CMD_READ is a bit problematic for me as I don't have really
  234. ;                state of the art machine on the other end and it can't feed
  235. ;                the card at the full speed. However Tundrah also told me
  236. ;                that for some reason MiamiDx is slow compared to Genesis. I
  237. ;                did some tests with both MiamiDx and Genesis, used ftp
  238. ;                client AmFTP 1.92 and ftpd Version 6.2/OpenBSD/Linux-0.10.
  239. ;                Download speed with Genesis was 720kb/s and with MiamiDx 530
  240. ;                kb/s. Genesis is %33 faster. For fucks sake wtf Miami is
  241. ;                doing? busyloops or what? :) This probably means that
  242. ;                someone should make a MNI driver. Any volunteers?
  243. ;
  244. ;              - Forget that mumbo jumbo about MMU speedup hack that was
  245. ;                mentioned in v1.2b2. 1) no real speedup due the way I/O
  246. ;                is accessed. 2) many amiga 060 turbo cards don't have
  247. ;                special hardware to handle writebuffer burst write ->
  248. ;                undefined behavior. (Thanks to Ralph Schmidt for helping me
  249. ;                understand this)
  250. ;
  251. ;              - Bugfix: AbortIO failed to abort S2_MULTICAST or S2_BROADCAST
  252. ;                requests.
  253. ;                
  254. ;                        *** internal 1.2beta3 release ***
  255. ;
  256. ;19-5-00 v1.2b4  Misc little changes here and there, nothing major.
  257. ;
  258. ;              - Speedup: inlined optimized version of RemoteRead for reading
  259. ;                prhdr and etherheader. Joined rx_header and rxbuffer. As a
  260. ;                result code simplified and sped up. For me the speedup is
  261. ;                +2kb/s. Inlined couple of other subroutines that are called
  262. ;                only once.
  263. ;
  264. ;              - Speedup: Got a report from darza saying that turboio indeed
  265. ;                is faster with `cnet' card. He got 720kb/s with v1.1,
  266. ;                v1.2beta1 and v1.2beta3, but 750kb/s with v1.2beta2. Eek! :)
  267. ;                Tweaked makefile to compile separate turboio version. It is
  268. ;                up to user to find out which one is faster. Currently non-
  269. ;                turboio ftp download peaked 754kb/s. Turboio version peaked
  270. ;                771kb/s. Could be that turboio is faster on 060 @ 50 systems
  271. ;                and non-turboio on overclocked 060 systems. Why? Maybe some
  272. ;                I/O timing issues... No idea really, just guessing. Need to
  273. ;                ask Tundrah to do more benchmarking. :)
  274. ;
  275. ;              - Improvements: added support for S2_ADDMULTICASTADDRESSES and
  276. ;                S2_DELMULTICASTADDRESSES (Multicast address range extensions
  277. ;                to SANA-II Rev 3). Implemented S2_ADDMULTICASTADDRESS and
  278. ;                S2_DELMULTICASTADDRESS using range of addr -> addr. Added
  279. ;                CPU type to version string. Added 68020 CPU check to 68020+
  280. ;                version. Device IDString no longer has '$VER: ' included.
  281. ;                Now uses CARDF_POSTSTATUS instead of a hack if card.resource
  282. ;                V39+ is available (note that KS 3.0 has *V37* card.resource,
  283. ;                and KS 3.1 has V40). Added workaround for Genesis bug, it
  284. ;                calls S2_ONLINE before S2_CONFIGINTERFACE.
  285. ;
  286. ;                        *** internal 1.2beta4 release ***
  287. ;
  288. ;25-5-00 v1.2  - Made compile with standard os-includes.
  289. ;
  290. ;                        *** 9th Aminet release ***
  291. ;
  292.  
  293.  
  294. ; todo: Do some more 020+ optimizations (the ones that really pay off!)
  295. ;       Make it use memory pool (not really worth it I think)
  296. ;       CopyTo/CopyFrom 16/32 support? (ADCD_2.1:DevInfo/Networking/SANA2Revision3)
  297. ;       Add support for more cards? (not in this device in this life, unless easily implemented)
  298. ;
  299.  
  300.  
  301. ; configured from makefile
  302. ;debug = 1
  303. ;verbose=1
  304. ;turboio = 1
  305.  
  306.  
  307. ; misc flags
  308. ;realdisable=1   ; use exec functions or macros ?
  309.  
  310.  
  311.  include exec/types.i
  312.  include exec/nodes.i
  313.  include exec/lists.i
  314.  include exec/libraries.i
  315.  include exec/errors.i
  316.  include exec/initializers.i
  317.  include exec/resident.i
  318.  include exec/memory.i
  319.  include exec/interrupts.i
  320.  include exec/semaphores.i
  321.  include exec/ports.i
  322.  include exec/io.i
  323.  include exec/devices.i
  324.  include exec/tasks.i
  325.  include devices/timer.i
  326.  IFND realdisable
  327.  include exec/ables.i
  328.  ENDC
  329.  
  330.  include funcdef.i
  331.  include exec/exec_lib.i
  332.  
  333.  IFND _LVOGetSysTime
  334. _LVOGetSysTime = -66          ; timer lib function
  335.  ENDC
  336.  IFND _LVOGetTagData
  337. _LVOGetTagData = -36          ; utility lib function
  338.  ENDC
  339.  
  340.  include pcmcia.i     ; card.resource etc.
  341.  include sanaii.i     ; the essential network stuff
  342.  include cnet.i       ; hardware specific stuff
  343.  
  344.  
  345. VERSION  = 1
  346. REVISION = 2
  347.  
  348. VERSTR macro
  349.  dc.b   "1.2 (25.5.2000)"
  350.  endm
  351.  
  352.  
  353. ; 1uS delay before nic register access
  354. ; May not be required with slower CPUs.
  355.  
  356. delay MACRO
  357. ; tst.b   $bfe001             ; at least 1uS, even on fast machines
  358.  ENDM
  359.  
  360.  
  361. MYDISABLE MACRO
  362.  IFD     realdisable
  363.  jsr     _LVODisable(a6)
  364.  ELSE
  365.  MOVE.W  #$4000,$DFF09A
  366.  ADDQ.B  #1,IDNestCnt(A6)
  367.  ENDC
  368.  ENDM
  369.  
  370. MYENABLE MACRO
  371.  IFD     realdisable
  372.  jsr     _LVOEnable(a6)
  373.  ELSE
  374.  SUBQ.B  #1,IDNestCnt(A6)
  375.  BGE.S   .MYENABLE\@
  376.  MOVE.W  #$C000,$DFF09A
  377. .MYENABLE\@:
  378.  ENDC
  379.  ENDM
  380.  
  381. MYREMHEAD MACRO
  382.  MOVE.L  (A0),A1
  383.  MOVE.L  (A1),D0
  384.  BEQ.S   .MYREMHEAD\@
  385.  MOVE.L  D0,(A0)
  386.  EXG.L   D0,A1
  387.  MOVE.L  A0,LN_PRED(A1)
  388. .MYREMHEAD\@
  389.  ENDM
  390.  
  391. ;===========================================================================
  392.  
  393.  
  394.     section 0,CODE
  395.  
  396.  
  397. ;-----------------------------------------------------------------------
  398. ; The first executable location.  This should return an error
  399. ; in case someone tried to run you as a program (instead of
  400. ; loading you as a device).
  401.  
  402. start_exe:
  403.  moveq   #-1,d0   ; it's a device, not an application!
  404.  rts
  405.  
  406.  
  407. ;-----------------------------------------------------------------------
  408. ; A romtag structure.  After your driver is brought in from disk, the
  409. ; disk image will be scanned for this structure to discover magic constants
  410. ; about you (such as where to start running you from...).
  411. ;-----------------------------------------------------------------------
  412.  
  413. romtag:
  414.  dc.w    RTC_MATCHWORD   ; RT_MATCHWORD
  415.  dc.l    romtag          ; RT_MATCHTAG
  416.  dc.l    Endcode         ; RT_ENDSKIP
  417.  dc.b    RTF_AUTOINIT    ; RT_FLAGS
  418.  dc.b    VERSION         ; RT_VERSION
  419.  dc.b    NT_DEVICE       ; RT_TYPE
  420.  dc.b    0               ; RT_PRI
  421.  dc.l    DeviceName      ; RT_NAME
  422.  dc.l    IDString        ; RT_IDSTRING
  423.  dc.l    Init            ; RT_INIT
  424.  
  425. Init:
  426.  dc.l    dd_extsize      ; data space size
  427.  dc.l    funcTable       ; pointer to function initializers
  428.  dc.l    dataTable       ; pointer to data initializers
  429.  dc.l    initRoutine     ; routine to run at startup
  430.  
  431. funcTable:
  432.  dc.w  -1
  433.  dc.w  Open_Device-funcTable
  434.  dc.w  Close_Device-funcTable
  435.  dc.w  Expunge_Device-funcTable
  436.  dc.w  _Null-funcTable
  437.  dc.w  _DevBeginIO-funcTable
  438.  dc.w  _DevAbortIO-funcTable
  439.  dc.w  -1
  440.  
  441. dataTable:
  442.  INITBYTE LN_TYPE,NT_DEVICE
  443.  INITLONG LN_NAME,DeviceName
  444.  INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  445.  INITWORD LIB_VERSION,VERSION
  446.  INITWORD LIB_REVISION,REVISION
  447.  INITLONG LIB_IDSTRING,idString
  448.  dc.w   0
  449.  
  450.  
  451.  include debugs.i
  452.  
  453.  
  454.  
  455. ;=======================================================
  456. ;                      initRoutine
  457. ;=======================================================
  458. ;
  459. ; This routine gets called after the device has been allocated.
  460. ; The device pointer is in d0.  The AmigaDOS segment list is in a0.
  461. ; If it returns the device pointer, then the device will be linked
  462. ; into the device list. If it returns NULL, then the device will
  463. ; be unloaded. This call is single-threaded.
  464. ;
  465. ; input:   a0 = seglist
  466. ;          d0 = device
  467. ;          a6 = execbase
  468. ;
  469. initRoutine:
  470.  movem.l d1-d7/a0-a5,-(sp)
  471.  move.l  d0,a5
  472.  move.l  a0,a4
  473.  
  474.  ifge    __CPU-68020
  475.  btst    #AFB_68020,AttnFlags+1(a6)
  476.  beq.s   .err
  477.  endc
  478.  
  479.  lea     utilityName(pc),a1
  480.  moveq   #36,d0
  481.  jsr     _LVOOpenLibrary(a6)
  482.  move.l  d0,utility_base     ; store utilitybase
  483.  beq.s   .err                ; oops failed, return failure
  484.  
  485.  move.l  a4,dd_SegList(a5)   ; seglist for expunge
  486.  move.l  a6,exec_base        ; local copy of execbase
  487.  move.l  a5,me_myself        ; for speedup
  488.  
  489.  move.l  a5,d0
  490. .pop:
  491.  movem.l (sp)+,d1-d7/a0-a5
  492.  rts
  493.  
  494. .err:
  495.  moveq   #0,d0
  496.  bra.s   .pop
  497.  
  498.  
  499. _Null:
  500.  moveq   #0,d0
  501.  rts
  502.  
  503.  
  504.  
  505.  
  506. ;----------------------------------------------------------------------
  507. ;
  508. ; Here begins the system interface commands. When the user calls
  509. ; OpenDevice/CloseDevice/RemDevice, this eventually gets translated
  510. ; into a call to the following routines (Open_Device/Close_Device/
  511. ; Expunge_Device). Exec has already put our device pointer in a6 for
  512. ; us.
  513.  
  514.  
  515.  
  516. ;=================================================================
  517. ;                         Open Device
  518. ;=================================================================
  519. ;
  520. ; error = Open_Device(device, ioreq, unitnum, flags)
  521. ;  d0                   a6      a1     d0      d1
  522. ;
  523. ; Open sets the IO_ERROR field on an error. If it was successfull,
  524. ; we should also set up the IO_UNIT and LN_TYPE fields. Exec takes
  525. ; care of setting up IO_DEVICE.
  526. ;
  527. Open_Device:
  528. ;
  529. ;** Subtle point: any AllocMem() call can cause a call to this device's
  530. ;** expunge vector. If LIB_OPENCNT is zero, the device might get expunged.
  531. ;
  532.  addq.w  #1,lib_opencnt(a6)          ; Fake an opener for duration of call <|>
  533.  
  534.  bug     <10,"cnet: OpenDevice(ioreq $%lx, unit %ld, flags $%02lx)",10>,a1,d0,d1
  535.  
  536.  ifgt    0
  537.  ifd     debug
  538.  ifd     verbose
  539.  move.l  #100000,d0
  540. .wait:
  541.  tst.b   $bfe001
  542.  subq.l  #1,d0
  543.  bne.s   .wait
  544.  endc
  545.  endc
  546.  endc
  547.  
  548.  movem.l d2-d4/a2-a4/a6,-(sp)
  549.  move.l  a6,a3                       ; a3 = device
  550.  move.l  a1,a4                       ; a4 = ioreq
  551.  move.l  d0,d4                       ; d4 = unit
  552.  
  553.  cmp.w   #IOS2_SIZE,mn_length(a4)    ; reject invalid requests
  554.  blt     .badcaller
  555.  
  556.  btst    #DDB_MINE,dd_flags2(a3)
  557.  bne     .isexclusive
  558.  
  559.  btst    #SANA2OPB_MINE,d1           ; want exclusive mode ?
  560.  beq.s   .init
  561.  
  562.  cmp.w   #1,lib_opencnt(a3)          ; must not be any other openers
  563.  bne     .isnonexcl
  564.  bset    #DDB_MINE,dd_flags2(a3)     ; set exclusive mode
  565.  btst    #SANA2OPB_PROM,d1
  566.  beq.s   .init
  567.  bset    #DDB_PROM,dd_flags2(a3)     ; set promiscuous mode
  568. .init:
  569.  
  570.  
  571.  move.l  a3,a1
  572.  bsr     init_device                 ; init device data structures
  573.  
  574.  move.l  a3,a0
  575.  move.l  a4,a1
  576.  move.l  d4,d0
  577.  bsr     Open_Unit                   ; open unit
  578.  move.l  d0,io_unit(a4)
  579.  beq     .openerr
  580.  
  581.  
  582.  btst    #DDB_NICUP,dd_flags(a3)     ; nic already initialised ?
  583.  bne.s   .nickdone
  584.  move.l  a3,a1
  585.  bsr     init_card                   ; init PCMCIA card
  586.  tst.l   d0
  587.  bne.s   .error
  588.  move.l  a3,a1
  589.  bsr     init_nic                    ; set up nic
  590.  tst.l   d0
  591.  bne.s   .error
  592. .nickdone:
  593.  
  594.  
  595.  
  596.  btst    #DDB_OFFLINE,dd_flags(a3)   ; previously put offline ?
  597.  bne.s   .opened
  598.  bset    #DDB_ONLINE,dd_flags(a3)    ; ready to accept packets
  599. .opened:
  600.  
  601.  
  602.  clr.b   io_error(a4)                ; IMPORTANT: Mark IORequest as "complete"
  603.  move.b  #NT_REPLYMSG,ln_type(a4)
  604.  addq.w  #1,lib_OpenCnt(a3)          ; opened successfully
  605.  bclr    #LIBB_DELEXP,lib_flags(a3)  ; prevent delayed expunges
  606.  
  607.  moveq   #0,d0
  608.  bug     <"cnet: OpenDevice OK",10,10>
  609.  
  610.  
  611. .done:
  612.  movem.l (sp)+,d2-d4/a2-a4/a6
  613.  subq.w  #1,lib_opencnt(a6)          ; ** End of expunge protection <|>
  614.  rts
  615.  
  616.  
  617.  
  618. .badcaller
  619.  bug     <"cnet: OpenDevice invalid MN_LENGTH!",10>
  620.  bra.s   .openerr
  621.  
  622. .isexclusive:
  623.  bug     <"cnet: device already in use exclusively!",10>
  624.  bra.s   .openerr
  625.  
  626. .isnonexcl:
  627.  bug     <"cnet: device already in use non-exclusively!",10>
  628.  bra.s   .openerr
  629.  
  630. .notask:
  631.  ; task creation failed, cleanup; kill the nic!
  632.  move.l  a3,a1
  633.  bsr     kill_nic
  634.  
  635. .error:
  636.  move.l  dd_cardres(a3),d0           ; did card.resource open ?
  637.  beq.s   .nocard
  638.  move.l  d0,a6
  639.  bclr    #DDB_OWNED,dd_flags(a3)     ; did we own card ?
  640.  beq.s   .nocard
  641.  lea     dd_cardhandle(a3),a1
  642.  moveq   #CARDF_REMOVEHANDLE,d0
  643.  jsr     _LVOReleaseCard(a6)         ; release card
  644. .nocard:
  645.  
  646.  
  647.  move.l  ios2_buffermanagement(a4),d0
  648.  beq.s   .nobufman                    ; got a buffermanagement pointer ?
  649.  clr.l   ios2_buffermanagement(a4)
  650.  
  651.  move.l  exec_base(pc),a6
  652.  
  653.  move.l  d0,a1
  654.  move.l  d0,a2
  655.  bug     <"cnet: OpenDevice remove bufman at $%lx",10>,a1
  656.  MYDISABLE                            ; lock access to list
  657.  REMOVE                               ; remove bufman struct from list
  658.  MYENABLE                             ; release lock on list
  659.  move.l  a2,a1
  660.  moveq   #bufman_sizeof,d0
  661.  jsr     _LVOFreeMem(a6)              ; discard buffer management struct
  662. .nobufman:
  663.  
  664.  
  665. .openerr:
  666.  moveq   #IOERR_OPENFAIL,d0          ; error, opendevice failed!
  667.  move.b  d0,io_error(a4)
  668.  move.l  d0,io_unit(a4)
  669.  move.l  d0,io_device(a4)            ; IMPORTANT: trash IO_DEVICE on open failure
  670.  bug     <"cnet: OpenDevice failed!",10,10>
  671.  bra.s   .done
  672.  
  673.  
  674.  
  675. ;===============================================================
  676. ;                 unit=Open Unit(device, ioreq, unitnum)
  677. ;                  d0              a0      a1     d0
  678. ;===============================================================
  679. ;
  680. ; Get the caller's buffer copy callback vectors
  681. ;
  682. Open_Unit:
  683.  bug     <"cnet: Open_Unit(ioreq $%08lx) taglist: $%08lx",10>,a1,ios2_buffermanagement(a1)
  684.  
  685.  movem.l d2-d6/a2-a5,-(sp)
  686.  move.l  a0,a4                    ; a4 = device
  687.  move.l  a1,a5                    ; a5 = ioreq
  688.  tst.l   d0                       ; only unit 0 is supported
  689.  bne     .error
  690.  
  691. ; If null taglist is supplied we don't fail!
  692.  
  693.  move.l  ios2_buffermanagement(a5),d0  ; tag list supplied?
  694.  beq     .ok
  695.  moveq   #0,d2                    ; d2 = tags found
  696.  move.l  d0,a2                    ; a2 = tag list
  697.  
  698. ; Note: I don't complain if I can't find pointers to the callback
  699. ; routines. This is because there are some programs that may need to
  700. ; open the device, but will never use any device commands that
  701. ; require the callbacks. Instead I check on CMD_READ, CMD_READORPHAN
  702. ; and CMD_WRITE for missing routines.
  703.  
  704.  move.l  exec_base(pc),a6
  705.  
  706.  moveq   #bufman_sizeof,d0        ; allocate memory for bufman vectors
  707.  moveq   #MEMF_PUBLIC,d1
  708.  jsr     _LVOAllocMem(a6)
  709.  move.l  d0,ios2_buffermanagement(a5)  ; return bufman node
  710.  beq     .error
  711.  
  712.  move.l  d0,a3
  713.  
  714.  move.l  utility_base(pc),a6
  715.  
  716.  ; get copyfrom functions:
  717.  
  718.  move.l  #S2_COPYFROMBUFF,d0
  719.  moveq   #0,d1
  720.  move.l  a2,a0
  721.  jsr     _LVOGetTagData(a6)
  722.  move.l  d0,bufman_copyfrombuf(a3)
  723.  
  724. ; This is new SANA-II V3 Addition
  725.  
  726.  move.l  #S2_DMACopyFromBuff32,d0
  727.  moveq   #0,d1
  728.  move.l  a2,a0
  729.  jsr     _LVOGetTagData(a6)
  730.  move.l  d0,bufman_dmacopyfrombuf32(a3)
  731.  
  732.  bug     <"cnet: S2_DMACopyFromBuff32 = $%08lx",10>,d0
  733.  
  734.  ; get copyto functions:
  735.  
  736.  move.l  #S2_COPYTOBUFF,d0
  737.  moveq   #0,d1
  738.  move.l  a2,a0
  739.  jsr     _LVOGetTagData(a6)
  740.  move.l  d0,bufman_copytobuf(a3)
  741.  
  742. ; This is new for SANA-II V3 Addition
  743.  
  744.  move.l  #S2_DMACopyToBuff32,d0
  745.  moveq   #0,d1
  746.  move.l  a2,a0
  747.  jsr     _LVOGetTagData(a6)
  748.  move.l  d0,bufman_dmacopytobuf32(a3)
  749.  
  750.  bug     <"cnet: S2_DMACopyToBuff32 = $%08lx",10>,d0
  751.  
  752. ; And this is new SANA-II V2 Addition
  753.  move.l  #S2_PACKETFILTER,d0
  754.  moveq   #0,d1
  755.  move.l  a2,a0
  756.  jsr     _LVOGetTagData(a6)
  757.  move.l  d0,bufman_packetfilter(a3)    ; if null everything get thru
  758.  
  759.  ifd     debug
  760.  bug     <"cnet: S2_PacketFilter = $%08lx",10>,d0
  761.  ifd     verbose
  762.  tst.l   d0
  763.  beq.s   .v1
  764.  move.l  d0,a0
  765.  bug     <"cnet: PacketFilter h_Entry = $%08lx h_SubEntry = $%08lx h_Data = $%08lx",10>,8(a0),12(a0),16(a0)
  766. .v1:
  767.  
  768.  move.l  #S2_COPYFROMBUFF16,d0
  769.  moveq   #0,d1
  770.  move.l  a2,a0
  771.  jsr     _LVOGetTagData(a6)
  772.  bug     <"cnet: S2_CopyFromBuff16 = $%08lx",10>,d0
  773.  
  774.  move.l  #S2_COPYTOBUFF16,d0
  775.  moveq   #0,d1
  776.  move.l  a2,a0
  777.  jsr     _LVOGetTagData(a6)
  778.  bug     <"cnet: S2_CopyToBuff16 = $%08lx",10>,d0
  779.  
  780.  move.l  #S2_COPYFROMBUFF32,d0
  781.  moveq   #0,d1
  782.  move.l  a2,a0
  783.  jsr     _LVOGetTagData(a6)
  784.  bug     <"cnet: S2_CopyFromBuff32 = $%08lx",10>,d0
  785.  
  786.  move.l  #S2_COPYTOBUFF32,d0
  787.  moveq   #0,d1
  788.  move.l  a2,a0
  789.  jsr     _LVOGetTagData(a6)
  790.  bug     <"cnet: S2_CopyToBuff32 = $%08lx",10>,d0
  791.  
  792.  endc
  793.  endc
  794.  
  795.  move.l  exec_base(pc),a6
  796.  
  797.  ; Init the list for CMD_READ requests
  798.  lea     bufman_rxqueue(a3),a0
  799.  NEWLIST a0
  800.  
  801.  bug     <"cnet: addbufman at $%lx",10>,a3
  802.  lea     dd_bufmanlist(a4),a0
  803.  move.l  a3,a1
  804.  MYDISABLE                        ; lock access to list
  805.  ADDHEAD                          ; add to buffer management list
  806.  MYENABLE                         ; release lock on list
  807.  bra.s   .ok
  808.  
  809. .error:
  810.  moveq   #0,d0                    ; return error
  811.  bra.s   .done
  812.  
  813. .ok:
  814.  moveq   #1,d0                    ; return OK
  815. .done:
  816.  movem.l (sp)+,d2-d6/a2-a5
  817.  rts
  818.  
  819.  
  820.  
  821. ;============================================================
  822. ;                      Close Device
  823. ;============================================================
  824. ;
  825. ;  Seglist = CloseDevice(ioreq, device)
  826. ;    d0                    a1    a6
  827. ;
  828. ;
  829. ; There are two different things that might be returned from the Close
  830. ; routine. If the device wishes to be unloaded, then Close must return
  831. ; the segment list (as given to Init). Otherwise close MUST return NULL.
  832. ;
  833. ;
  834. Close_Device:
  835.  bug     <10,"cnet: CloseDevice(ioreq $%08lx)",10>,a1
  836.  
  837.  ifgt    0
  838.  ifd     debug
  839.  ifd     verbose
  840.  move.l  #100000,d0
  841. .wait:
  842.  tst.b   $bfe001
  843.  subq.l  #1,d0
  844.  bne.s   .wait
  845.  endc
  846.  endc
  847.  endc
  848.  
  849.  movem.l a2-a4/a6,-(sp)
  850.  move.l  a1,a3                        ; a3 = ioreq
  851.  move.l  a6,a4                        ; a4 = device
  852.  
  853.  moveq   #0,d0                        ; default: no unload
  854.  tst.w   lib_OpenCnt(a4)
  855.  beq     .done                        ; invalid state!
  856.  
  857.  move.l  exec_base(pc),a6
  858.  
  859.  moveq   #-1,d0
  860.  move.l  d0,io_unit(a3)               ; We're closed...
  861.  move.l  d0,io_device(a3)             ; customers not welcome at this IORequest!!
  862.  
  863.  move.l  ios2_buffermanagement(a3),d0
  864.  beq.s   .nobufman                    ; got a buffermanagement pointer ?
  865.  clr.l   ios2_buffermanagement(a3)
  866.  
  867.  move.l  d0,a1
  868.  move.l  d0,a2
  869.  bug     <"cnet: remove bufman at $%lx",10>,a1
  870.  
  871.  MYDISABLE                            ; lock access to list
  872.  REMOVE                               ; remove bufman struct from list
  873.  MYENABLE                             ; release lock on list
  874.  
  875.  move.l  a2,a1
  876.  moveq   #bufman_sizeof,d0
  877.  jsr     _LVOFreeMem(a6)              ; discard buffer management struct
  878. .nobufman:
  879.  
  880.  
  881.  moveq   #0,d0                        ; default: no unload
  882.  subq.w  #1,lib_OpenCnt(a4)           ; one less opener
  883.  bne.s   .done                        ; still open ?
  884.  
  885.  bug     <"cnet: devclosedown",10>
  886.  
  887. ; close down the devive
  888.  move.l  a4,a1
  889. ; a6 = execbase
  890.  bsr     devclosedown
  891.  
  892.  moveq   #0,d0                        ; default: no unload
  893.  btst    #LIBB_DELEXP,lib_flags(a4)
  894.  beq.s   .done                        ; delayed expunge pending ?
  895.  
  896. ;  do the expunge
  897.  bug     <"cnet: LIBF_DELEXP calling Expunge!",10>
  898.  move.l  a4,a6
  899.  bsr.s   Expunge_Device
  900.  
  901. .done:
  902.  movem.l (sp)+,a2-a4/a6
  903.  bug     <"cnet: CloseDevice return: $%08lx",10,10>,d0
  904.  rts                                  ; MUST return either zero or the SegList!!!
  905.  
  906.  
  907.  
  908. ;============================================================
  909. ;                      Expunge Device
  910. ;============================================================
  911. ;
  912. ;  Seglist = ExpungeDevice(device)
  913. ;    d0                      a6
  914. ;
  915. ; Expunge is called by the memory allocator when the system is low on
  916. ; memory (or by us from the CloseDevice above!).
  917. ;
  918. ; There are two different things that might be returned from the Expunge
  919. ; routine.  If the device is no longer open then Expunge may return the
  920. ; segment list (as given to Init). Otherwise Expunge may set the delayed
  921. ; expunge flag and return NULL.
  922. ;
  923. ; One other important note: because Expunge is called from the memory
  924. ; allocator, it may NEVER Wait() or otherwise take long time to complete.
  925. ;
  926. ;
  927. Expunge_Device:
  928.  bug     <10,"cnet: Expunge_Device $%08lx",10>,a6
  929.  
  930.  ifgt    0
  931.  ifd     debug
  932.  ifd     verbose
  933.  move.l  #100000,d0
  934. .wait:
  935.  tst.b   $bfe001
  936.  subq.l  #1,d0
  937.  bne.s   .wait
  938.  endc
  939.  endc
  940.  endc
  941.  
  942.  tst.w   lib_opencnt(a6)
  943.  beq.s   .unload                      ; anyone has us open ?
  944.  
  945. ; it is still open. set the delayed expunge flag
  946.  
  947.  bug     <"cnet: Could not expunge, LIBF_DELEXP set!",10>
  948.  bset    #LIBB_DELEXP,lib_flags(a6)
  949.  moveq   #0,d0                        ; do not unload the seg
  950.  rts
  951.  
  952.  
  953. .unload
  954.  bug     <"cnet: Unloading...",10>
  955.  
  956.  movem.l a4/a6,-(sp)
  957.  move.l  dd_SegList(a6),-(sp)         ; seglist to return in d0
  958.  
  959.  move.l  a6,a4
  960.  move.l  exec_base(pc),a6
  961.  
  962. ; put the hardware offline
  963.  move.l  a4,a1
  964. ; a6=execbase
  965.  bug     <"cnet: devclosedown",10>
  966.  bsr     devclosedown
  967.  
  968.  
  969. ; get rid of the timer.device stuff we might have allocated:
  970.  lea     timereq(pc),a1
  971.  move.l  io_device(a1),d0
  972.  beq.s   .notimerdev                  ; was timer ever opened?
  973.  addq.l  #1,d0
  974.  beq.s   .notimerdev                  ; error can be also indicated by -1!
  975.  bug     <"cnet: closedevice timer ior $%08lx",10>,a1
  976.  jsr     _LVOCloseDevice(a6)          ; close it
  977. .notimerdev
  978.  
  979.  
  980. ; release the card, if we own it. note that there is
  981. ; no CloseResource() call.
  982.  move.l  dd_cardres(a4),d0           ; did we open card.resource at some point ?
  983.  beq.s   .nocard
  984.  bclr    #DDB_OWNED,dd_flags(a4)     ; do we own card ?
  985.  beq.s   .nocard
  986.  move.l  a6,-(sp)
  987.  move.l  d0,a6
  988.  lea     dd_cardhandle(a4),a1
  989.  moveq   #CARDF_REMOVEHANDLE,d0
  990.  bug     <"cnet: releasing cardhandle $%08lx",10>,a1
  991.  jsr     _LVOReleaseCard(a6)         ; release card
  992.  move.l  (sp)+,a6
  993. .nocard:
  994.  
  995.  
  996. ; close utilitybase
  997.  move.l  utility_base(pc),a1
  998.  bug     <"cnet: closing utilitybase $%08lx",10>,a1
  999.  jsr     _LVOCloseLibrary(a6)
  1000.  
  1001.  
  1002.  ; unlink from device list
  1003.  move.l  a4,a1
  1004.  bug     <"cnet: removing device node $%08lx",10>,a1
  1005.  REMOVE
  1006.  
  1007.  
  1008. ; free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
  1009.  moveq   #0,d0
  1010.  move.l  a4,a1                        ; devicebase
  1011.  move.w  lib_negsize(a4),d0
  1012.  sub.l   d0,a1                        ; calculate base of functions
  1013.  add.w   lib_possize(a4),d0           ; calculate size of functions + data area
  1014.  jsr     _LVOFreeMem(a6)
  1015.  
  1016.  bug     <"cnet: Unload done! cnet.device expunged!",10,10>
  1017.  
  1018.  movem.l (sp)+,d0/a4/a6               ; pop regs and seglist pointer
  1019.  rts
  1020.  
  1021.  
  1022.  
  1023. ;======================================================================
  1024. ;                  devclosedown(device, execbase)
  1025. ;                                a1       a6
  1026. ;======================================================================
  1027. ;
  1028. ; Put the nic into sleep... also do whatever nececcary hw magic
  1029. ; before device closedown. mark the device offline and unconfigured.
  1030. ;
  1031. devclosedown:
  1032. ;and.b   #~(DDF_ONLINE|DDF_CONFIGURED),dd_flags(a1) ; not online, not configured
  1033.  and.b   #~DDF_ONLINE,dd_flags(a1)                  ; not online
  1034.  and.b   #~(DDF_MINE|DDF_PROM),dd_flags2(a1)        ; cancel exclusive mode, cancel promiscuous mode
  1035.  bra     kill_nic                                   ; stop controller
  1036.  
  1037.  
  1038.  
  1039. ;===============================================================
  1040. ;                       Dev_BeginIO
  1041. ;===============================================================
  1042. ; the entry point for all device commands
  1043. ;
  1044.  
  1045.  CNOP 0,4
  1046.  
  1047. _DevBeginIO:
  1048.  move.w  io_command(a1),d0       ; get command number
  1049.  move.b  #NT_MESSAGE,ln_type(a1) ; make sure type is message
  1050.  cmp.w   #S2_END,d0
  1051.  bhs     .berror                 ; valid command?
  1052.  lsl.w   #2,d0
  1053.  move.l  .cmds(pc,d0.w),d0        ; get command vector
  1054.  bne.s   .ok
  1055. .error:
  1056.  move.b  #IOERR_NOCMD,io_error(a1)
  1057.  bra     TermIO                  ; return invalid command
  1058. .ok:
  1059.  move.l  d0,a0
  1060.  clr.b   io_error(a1)            ; no errors yet
  1061.  
  1062.  ifgt    0
  1063.  ifd     debug
  1064.  ifd     verbose
  1065.  moveq   #0,d0
  1066.  move.w  io_command(a1),d0
  1067.  bug <"cnet: BeginIO ioreq $%08lx cmd %ld",10>,a1,d0
  1068.  move.l  #300000,d0
  1069. .wait:
  1070.  tst.b   $bfe001
  1071.  subq.l  #1,d0
  1072.  bne.s   .wait
  1073.  endc
  1074.  endc
  1075.  endc
  1076.  
  1077.  jmp     (a0)                    ; jump to command
  1078.  
  1079.  
  1080. ; command vectors
  1081.  
  1082.  CNOP 0,4
  1083.  
  1084. .cmds:
  1085.  dc.l    0                           ;  0
  1086.  dc.l    0                           ;  1
  1087.  dc.l    devcmd_read                 ;  2 = cmd_read
  1088.  dc.l    devcmd_write                ;  3 = cmd_write
  1089.  dc.l    0                           ;  4
  1090.  dc.l    0                           ;  5
  1091.  dc.l    0                           ;  6
  1092.  dc.l    0                           ;  7
  1093.  dc.l    devcmd_flush                ;  8 = cmd_flush
  1094.  dc.l    devcmd_devicequery          ;  9 = S2_DEVICEQUERY
  1095.  dc.l    devcmd_getstationaddress    ;  10= S2_GETSTATIONADDRESS
  1096.  dc.l    devcmd_configinterface      ;  11= S2_CONFIGINTERFACE
  1097.  dc.l    0                           ;  12
  1098.  dc.l    0                           ;  13
  1099.  dc.l    devcmd_addmulticast         ;  14= S2_ADDMULTICASTADDRESS
  1100.  dc.l    devcmd_delmulticast         ;  15= S2_DELMULTICASTADDRESS
  1101.  dc.l    devcmd_multicast            ;  16= S2_MULTICAST
  1102.  dc.l    devcmd_broadcast            ;  17= S2_BROADCAST
  1103.  dc.l    devcmd_tracktype            ;  18= S2_TRACKTYPE
  1104.  dc.l    devcmd_untracktype          ;  19= S2_UNTRACKTYPE
  1105.  dc.l    devcmd_gettypestats         ;  20= S2_GETTYPESTATS
  1106.  dc.l    devcmd_getspecialstats      ;  21= S2_GETSPECIALSTATS
  1107.  dc.l    devcmd_getglobalstats       ;  22= S2_GETGLOBALSTATS
  1108.  dc.l    devcmd_onevent              ;  23= S2_ONEVENT
  1109.  dc.l    devcmd_readorphan           ;  24= S2_READORPHAN
  1110.  dc.l    devcmd_online               ;  25= S2_ONLINE
  1111.  dc.l    devcmd_offline              ;  26= S2_OFFLINE
  1112.  
  1113. .nsd_supported:
  1114.  dc.w 2,3
  1115.  dc.w 8,9,10,11
  1116.  dc.w 14,15,16,17,18,19,20,21,22,23,24,25,26
  1117.  dc.w NSCMD_DEVICEQUERY
  1118.  dc.w S2_ADDMULTICASTADDRESSES
  1119.  dc.w S2_DELMULTICASTADDRESSES
  1120.  dc.w 0
  1121.  
  1122. .berror:
  1123.  clr.b   io_error(a1)                ; no error
  1124.  cmp.w   #S2_ADDMULTICASTADDRESSES,d0
  1125.  beq     devcmd_addmulticasts
  1126.  cmp.w   #S2_DELMULTICASTADDRESSES,d0
  1127.  beq     devcmd_delmulticasts
  1128.  
  1129.  cmp.w   #NSCMD_DEVICEQUERY,d0       ; is it NSCMD_DEVICEQUERY?
  1130.  bne     .error
  1131.  
  1132.  ifd     verbose
  1133.  bug     <"cnet: NSCMD_DEVICEQUERY ior $%08lx",10>,a1
  1134.  endc
  1135.  cmp.l   #16,io_length(a1)
  1136.  blt     .error
  1137.  move.l  io_data(a1),d0
  1138.  beq     .error
  1139.  move.l  d0,a0
  1140.  tst.l   (a0)+
  1141.  bne     .error
  1142.  tst.l   (a0)
  1143.  bne     .error
  1144.  
  1145.  ifd     verbose
  1146.  bug     <"cnet: replied with NSDEVTYPE_SANA2!",10>
  1147.  endc
  1148.  moveq   #16,d0
  1149.  move.l  d0,(a0)+
  1150.  move.l  #$00070000,(a0)+            ; NSDEVTYPE_SANA2<<16
  1151.  move.l  #.nsd_supported,(a0)
  1152.  move.l  d0,io_actual(a1)
  1153.  bra     TermIO
  1154.  
  1155.  
  1156.  
  1157. ;====================================================================
  1158. ;                              Abort_IO
  1159. ;====================================================================
  1160. ;
  1161. ;                   try to cancel a pending ioreq
  1162. ;
  1163. _DevAbortIO:
  1164.  
  1165.  bug <"cnet: AbortIO ioreq $%08lx",10>,a1
  1166.  
  1167.  movem.l d2/a2-a4/a6,-(sp)
  1168.  move.l  a6,a4                            ; a4=device
  1169.  move.l  exec_base(pc),a6
  1170.  move.l  a1,a2                            ; a2=ioreq
  1171.  
  1172.  moveq   #0,d0                            ; if already replied silentry ignore
  1173.  MYDISABLE                                ; lock access to lists
  1174.  cmp.b   #NT_MESSAGE,ln_type(a2)          ; only cancel queued ioreq's
  1175.  bne.s   .done
  1176.  
  1177.  move.w  io_command(a2),d0
  1178.  cmp.w   #CMD_READ,d0
  1179.  beq.s   .read
  1180.  
  1181.  lea     dd_orphanlist(a4),a0
  1182.  cmp.w   #S2_READORPHAN,d0
  1183.  beq.s   .thisone
  1184.  
  1185.  lea     dd_writelist(a4),a0
  1186.  cmp.w   #CMD_WRITE,d0
  1187.  beq.s   .thisone
  1188.  cmp.w   #S2_MULTICAST,d0
  1189.  beq.s   .thisone
  1190.  cmp.w   #S2_BROADCAST,d0
  1191.  beq.s   .thisone
  1192.  
  1193.  lea     dd_eventlist(a4),a0
  1194.  cmp.w   #S2_ONEVENT,d0
  1195.  beq.s   .thisone
  1196.  
  1197.  bug <"cnet: AbortIO not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT",10>
  1198.  moveq   #IOERR_NOCMD,d0
  1199.  bra.s   .done
  1200.  
  1201. .read:
  1202. ; Check all nodes in dd_bufmanlist until we succeed to abort:
  1203. ; if we can't find the ioreq in any list, return IOERR_NOCMD.
  1204.  
  1205.  move.l  dd_bufmanlist(a4),a3
  1206. ;bug <"cnet: AbortIO READ bufmanlist 1st: $%08lx",10>,a3
  1207. .readhandle
  1208.  moveq   #IOERR_NOCMD,d0                  ; return failure if we can't find it
  1209.  move.l  (a3),d2
  1210.  beq.s   .done                            ; end of list?
  1211.  lea     bufman_rxqueue(a3),a0
  1212.  ; a2=ioreq
  1213.  bsr     AbortReq
  1214.  tst.l   d0
  1215.  beq.s   .done                            ; succeeded to abort?
  1216.  move.l  d2,a3
  1217.  bra.s   .readhandle
  1218.  
  1219. .thisone:
  1220.  ; a0=list where the ioreqs should be in
  1221.  ; a2=ioreq
  1222.  bsr     AbortReq
  1223.  
  1224. .done:
  1225.  MYENABLE                                 ; release lock on lists
  1226.  
  1227.  movem.l (sp)+,d2/a2-a4/a6
  1228.  rts
  1229.  
  1230.  
  1231.  
  1232. ;======================================================================
  1233. ;                  AbortReq(minlist, ioreq, execbase)
  1234. ;                             a0      a2      a6
  1235. ;======================================================================
  1236. ;
  1237. ; locate an IO request in a linked list and abort it if found.
  1238. ;
  1239. AbortReq:
  1240.  moveq   #IOERR_NOCMD,d0
  1241.  
  1242.  move.l  (a0),a0
  1243. .search:
  1244.  move.l  (a0),d1
  1245.  beq.s   .done                            ; end of list ?
  1246.  cmp.l   a2,a0                            ; = ioreq ?
  1247.  move.l  d1,a0                            ; note: movea doesn't change ccs!
  1248.  bne.s   .search
  1249.  
  1250.  move.l  a2,a1
  1251. ;bug <"cnet: AbortReq aborted $%08lx",10>,a1
  1252.  REMOVE                                   ; remove ioreq from list
  1253.  move.b  #NT_REPLYMSG,ln_type(a2)
  1254.  move.b  #IOERR_ABORTED,io_error(a2)
  1255.  move.l  a2,a1
  1256.  jsr     _LVOReplyMsg(a6)                 ; reply to originator's message
  1257.  moveq   #0,d0                            ; aborted OK
  1258. .done:
  1259.  rts
  1260.  
  1261.  
  1262.  
  1263. ;===========================================================
  1264. ;                      termio(ioreq)
  1265. ;                               a1
  1266. ;===========================================================
  1267. ;
  1268. ; return completed ioreq to sender.
  1269. ;
  1270. TermIO:
  1271.  move.b  #NT_REPLYMSG,ln_type(a1)
  1272.  btst    #IOB_QUICK,io_flags(a1)
  1273.  bne.s   .done                       ; does sender need a reply ?
  1274.  move.l  a6,-(sp)
  1275.  move.l  exec_base(pc),a6
  1276.  jsr     _LVOReplyMsg(a6)            ; send reply
  1277.  move.l  (sp)+,a6
  1278. .done:
  1279.  rts
  1280.  
  1281.  
  1282.  
  1283. ;====================================================
  1284. ;                     CMD_READ
  1285. ;====================================================
  1286. ;
  1287. ; if card is configured and online
  1288. ;
  1289.  CNOP 0,4
  1290. devcmd_read:
  1291.  ifd  verbose
  1292.  bug  <"cnet: cmd_read(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1293.  endc
  1294.  
  1295.  movem.l a2/a3/a6,-(sp)
  1296.  move.l  a1,a2                           ; a2 = ioreq
  1297.  move.l  io_device(a1),a3                ; a3 = device
  1298.  
  1299.  btst    #DDB_CONFIGURED,dd_flags(a3)    ; configured ?
  1300.  beq     .unconfigured
  1301.  btst    #DDB_ONLINE,dd_flags(a3)        ; online ?
  1302.  beq     .offline
  1303.  
  1304.  move.l  ios2_buffermanagement(a2),d0
  1305.  beq.s   .bad                            ; eeeekh, no bufman ?
  1306.  move.l  d0,a0
  1307.  tst.l   bufman_copytobuf(a0)
  1308.  beq.s   .bad                            ; this is needed for reading.. :)
  1309.  
  1310.  bclr    #IOB_QUICK,io_flags(a2)         ; must be queued
  1311.  move.l  exec_base(pc),a6
  1312.  
  1313. ; add to this ioreq's bufman_rxqueue
  1314.  
  1315.  lea     bufman_rxqueue(a0),a0
  1316.  move.l  a2,a1
  1317.  ifd     verbose
  1318.  bug     <"cnet: CMD_READ ior $%08lx added to bufman_rxqueue $%08lx",10>,a1,a0
  1319.  endc
  1320.  MYDISABLE
  1321.  ADDTAIL                                 ; add ioreq to read queue
  1322.  MYENABLE
  1323.  
  1324. .done:
  1325.  movem.l (sp)+,a2/a3/a6
  1326.  rts
  1327.  
  1328. .unconfigured:
  1329.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  1330.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1331.  bra.s   .error
  1332.  
  1333. .offline:
  1334.  moveq   #S2WERR_UNIT_OFFLINE,d0         ; error, device is offline
  1335.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1336.  bra.s   .error
  1337.  
  1338. .bad:
  1339.  moveq   #S2WERR_GENERIC_ERROR,d0        ; error, bad argument
  1340.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1341.  
  1342. .error:
  1343.  ifd     verbose
  1344.  bug     <"cnet: read ior $%08lx error %ld",10>,a2,d0
  1345.  endc
  1346.  
  1347.  move.l  d0,ios2_wireerror(a2)
  1348.  move.l  a2,a1
  1349.  bsr     TermIO
  1350.  bra.s   .done
  1351.  
  1352.  
  1353.  
  1354. ;====================================================
  1355. ;                     S2_READORPHAN
  1356. ;====================================================
  1357. ;
  1358. ; if card is configured and online
  1359. ;
  1360.  CNOP 0,4
  1361. devcmd_readorphan:
  1362.  bug     <"cnet: readorphan(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1363.  
  1364.  movem.l a2/a3/a6,-(sp)
  1365.  move.l  a1,a2                           ; a2 = ioreq
  1366.  move.l  io_device(a2),a3
  1367.  
  1368.  btst    #DDB_CONFIGURED,dd_flags(a3)    ; configured ?
  1369.  beq     .unconfigured
  1370.  btst    #DDB_ONLINE,dd_flags(a3)        ; online ?
  1371.  beq     .offline
  1372.  
  1373.  move.l  ios2_buffermanagement(a2),d0
  1374.  beq.s   .bad                            ; eeeekh, no bufman ?
  1375.  move.l  d0,a0
  1376.  tst.l   bufman_copytobuf(a0)
  1377.  beq.s   .bad                            ; this is needed for reading.. :)
  1378.  
  1379.  bclr    #IOB_QUICK,io_flags(a2)         ; must be queued
  1380.  move.l  exec_base(pc),a6
  1381.  lea     dd_orphanlist(a3),a0
  1382.  move.l  a2,a1
  1383.  bug     <"cnet: S2_READORPHAN ior $%08lx added to orphanlist $%08lx",10>,a1,a0
  1384.  MYDISABLE
  1385.  ADDTAIL                                 ; add ioreq to orphan queue
  1386.  MYENABLE
  1387.  
  1388. .done:
  1389.  movem.l (sp)+,a2/a3/a6
  1390.  rts
  1391.  
  1392. .unconfigured:
  1393.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  1394.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1395.  bra.s   .error
  1396.  
  1397. .offline:
  1398.  moveq   #S2WERR_UNIT_OFFLINE,d0         ; error, device is offline
  1399.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1400.  bra.s   .error
  1401.  
  1402. .bad:
  1403.  moveq   #S2WERR_GENERIC_ERROR,d0        ; error, bad argument
  1404.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1405.  
  1406. .error:
  1407.  ifd     verbose
  1408.  bug     <"cnet: readorphan ior $%08lx error %ld",10>,a2,d0
  1409.  endc
  1410.  
  1411.  move.l  d0,ios2_wireerror(a2)
  1412.  move.l  a2,a1
  1413.  bsr     TermIO
  1414.  bra.s   .done
  1415.  
  1416.  
  1417.  
  1418. ;======================================================
  1419. ;                      CMD_WRITE
  1420. ;======================================================
  1421. ;
  1422. ; if card is configured and online
  1423. ;
  1424.  CNOP 0,4
  1425. devcmd_write:
  1426.  ifd  verbose
  1427.  bug  <"cnet: cmd_write(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1428.  endc
  1429.  
  1430.  movem.l a2/a3/a6,-(sp)
  1431.  move.l  a1,a2                            ; a2 = ioreq
  1432.  move.l  io_device(a2),a3                 ; a3 = device
  1433.  
  1434.  btst    #DDB_CONFIGURED,dd_flags(a3)     ; configured ?
  1435.  beq     .unconfigured
  1436.  btst    #DDB_ONLINE,dd_flags(a3)         ; online ?
  1437.  beq     .offline
  1438.  
  1439. ; check ioreq's bufman validity
  1440.  
  1441.  move.l  ios2_buffermanagement(a2),d0
  1442.  beq.s   .bad                             ; eeeekh, no bufman ?
  1443.  move.l  d0,a0
  1444.  tst.l   bufman_copyfrombuf(a0)
  1445.  beq.s   .bad                             ; no routine for writing ?
  1446.  
  1447.  move.l  ios2_DataLength(a2),d1
  1448.  tst.b   io_flags(a2)                     ; (test SANA2IOB_RAW) raw packets ?
  1449.  bpl.s   .cooked
  1450.  
  1451.  cmp.l   #RAWPKT_SIZE,d1
  1452.  bls.s   .goodlen                         ; check packet size
  1453.  bra.s   .toobig
  1454.  
  1455. .cooked:
  1456.  cmp.l   #ETHERPKT_SIZE,d1
  1457.  bhi.s   .toobig
  1458.  
  1459. .goodlen:
  1460.  bclr    #IOB_QUICK,io_flags(a2)          ; must be queued
  1461.  move.l  exec_base(pc),a6
  1462.  lea     dd_writelist(a3),a0
  1463.  move.l  a2,a1
  1464.  ifd     verbose
  1465.  bug     <"cnet: CMD_WRITE ior $%08lx added to writelist $%08lx",10>,a1,a0
  1466.  endc
  1467.  MYDISABLE
  1468.  ADDTAIL                                  ; add ioreq to write queue
  1469.  MYENABLE
  1470.  
  1471.  lea     dd_txint(a3),a1
  1472.  jsr     _LVOCause(a6)                    ; start tx
  1473.  
  1474. .done:
  1475.  movem.l (sp)+,a2/a3/a6
  1476.  rts
  1477.  
  1478.  
  1479. .unconfigured:
  1480.  moveq   #S2WERR_NOT_CONFIGURED,d0        ; error, not configured
  1481.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1482.  bra.s   .error
  1483.  
  1484. .offline:
  1485.  moveq   #S2WERR_UNIT_OFFLINE,d0          ; error, device is offline
  1486.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1487.  bra.s   .error
  1488.  
  1489. .bad:
  1490.  moveq   #S2WERR_GENERIC_ERROR,d0         ; error, bad argument
  1491.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1492.  bra.s   .error
  1493.  
  1494. .toobig:
  1495.  moveq   #S2EVENT_TX,d0                   ; return any TX events
  1496.  bsr     DoEvent
  1497.  moveq   #0,d0
  1498.  move.b  #S2ERR_MTU_EXCEEDED,io_error(a2) ; oops! packet too big
  1499.  
  1500. .error:
  1501.  ifd     verbose
  1502.  bug     <"cnet: write ior $%08lx error %ld",10>,a2,d0
  1503.  endc
  1504.  
  1505.  move.l  d0,ios2_wireerror(a2)
  1506.  move.l  a2,a1
  1507.  bsr     TermIO
  1508.  bra.s   .done
  1509.  
  1510.  
  1511.  
  1512. ;==============================================
  1513. ;                CMD_FLUSH
  1514. ;==============================================
  1515. ;
  1516. devcmd_flush:
  1517.  movem.l a1-a2/a6,-(sp)
  1518.  move.l  exec_base(pc),a6
  1519.  move.l  io_device(a1),a2             ; a2 = device
  1520.  
  1521.  bug     <"cnet: CMD_FLUSH ior $%08lx device $%08lx",10>,a1,a2
  1522.  
  1523.  ifgt    0
  1524.  ifd     debug
  1525.  ifd     verbose
  1526.  bug <"cnet: delaying...",10>
  1527.  move.l  #500000,d0
  1528. .wait:
  1529.  tst.b   $bfe001
  1530.  subq.l  #1,d0
  1531.  bne.s   .wait
  1532.  endc
  1533.  endc
  1534.  endc
  1535.  
  1536.  MYDISABLE
  1537.  
  1538.  move.l  a2,a0
  1539.  moveq   #IOERR_ABORTED,d0
  1540.  moveq   #0,d1
  1541.  bsr     AbortRW
  1542.  
  1543.  lea     dd_eventlist(a2),a0          ; abort all Event requests
  1544.  moveq   #IOERR_ABORTED,d0
  1545.  moveq   #0,d1
  1546.  bsr     AbortList
  1547.  
  1548.  MYENABLE
  1549.  bug     <"cnet: CMD_FLUSH done",10>
  1550.  
  1551.  movem.l (sp)+,a1-a2/a6
  1552.  bra     TermIO
  1553.  
  1554.  
  1555.  
  1556. ;======================================================================
  1557. ;                  abortlist(list, errcode, wireerror, execbase)
  1558. ;                             a0     d0.b      d1.l      a6
  1559. ;======================================================================
  1560. ;
  1561. ; Aborts all ios2requs in given list with ios2_Error set to errcode
  1562. ; and ios2_wireerror set to wireerror.
  1563. ;
  1564. AbortList:
  1565.  movem.l d2-d3/a2,-(sp)
  1566.  move.l  a0,a2
  1567.  move.b  d0,d2
  1568.  move.l  d1,d3
  1569.  bra.s   .flush
  1570.  
  1571. .loop:
  1572.  move.l  d0,a1
  1573. ;move.b  #NT_REPLYMSG,ln_type(a1)
  1574.  move.b  d2,io_error(a1)
  1575.  move.l  d3,ios2_wireerror(a1)
  1576. ;bug     <"cnet: AbortList ior $%08lx",10>,a1
  1577.  jsr     _LVOReplyMsg(a6)
  1578. .flush:
  1579.  move.l  a2,a0
  1580.  MYREMHEAD
  1581.  bne.s   .loop
  1582.  
  1583.  movem.l (sp)+,d2-d3/a2
  1584.  rts
  1585.  
  1586.  
  1587.  
  1588. ;======================================================================
  1589. ;                  abortrw(device, errcode, wireerror, execbase)
  1590. ;                            a0      d0.b      d1.l      a6
  1591. ;======================================================================
  1592. ;
  1593. ; Aborts all pending reads and writes with ios2_Error set to errcode
  1594. ; and ios2_wireerror set to wireerror.
  1595. ;
  1596. AbortRW:
  1597.  movem.l d2-d4/a2-a3,-(sp)
  1598.  move.l  a0,a3
  1599.  move.b  d0,d2
  1600.  move.l  d1,d3
  1601.  
  1602.  move.l  dd_bufmanlist(a3),a2
  1603. .reado:
  1604.  move.l  (a2),d4
  1605.  beq.s   .flushrest
  1606.  bra.s   .flushreads
  1607.  
  1608. .readloop:
  1609.  move.l  d0,a1
  1610. ;move.b  #NT_REPLYMSG,ln_type(a1)
  1611.  move.b  d2,io_error(a1)
  1612.  move.l  d3,ios2_wireerror(a1)
  1613. ;bug     <"cnet: AbortRead ior $%08lx",10>,a1
  1614.  jsr     _LVOReplyMsg(a6)             ; abort all Read requests
  1615. .flushreads:
  1616.  lea     bufman_rxqueue(a2),a0
  1617.  MYREMHEAD
  1618.  bne.s   .readloop
  1619.  
  1620.  move.l  d4,a2
  1621.  bra.s   .reado
  1622. .flushrest:
  1623.  
  1624.  lea     dd_orphanlist(a3),a0         ; abort all ReadOrphan requests
  1625.  move.b  d2,d0
  1626.  move.l  d3,d1
  1627.  bsr     AbortList
  1628.  
  1629.  lea     dd_writelist(a3),a0          ; abort all Write requests
  1630.  move.b  d2,d0
  1631.  move.l  d3,d1
  1632.  bsr     AbortList
  1633.  
  1634.  movem.l (sp)+,d2-d4/a2-a3
  1635.  rts
  1636.  
  1637.  
  1638.  
  1639. ;==============================================
  1640. ;               S2_ONLINE
  1641. ;==============================================
  1642. ;
  1643. ;         Try to put device online
  1644. ;
  1645. devcmd_online:
  1646.  bug     <"cnet: s2_online",10>
  1647.  
  1648.  move.l  a1,-(sp)
  1649.  move.l  io_device(a1),a0               ; a0 = device
  1650.  
  1651. ; This is a workaround for Genesis.. it calls
  1652. ; S2_ONLINE before S2_CONFIGINTERFACE.
  1653.  btst    #DDB_ONLINE,dd_flags(a0)       ; already online ?
  1654.  bne.s   .done
  1655.  
  1656.  btst    #DDB_CONFIGURED,dd_flags(a0)   ; won't go online unless configured!
  1657.  beq.s   .unconfigured
  1658.  btst    #DDB_NICUP,dd_flags(a0)        ; nic initialised ?
  1659.  beq.s   .uninit
  1660.  
  1661.  bclr    #DDB_OFFLINE,dd_flags(a0)
  1662.  bset    #DDB_ONLINE,dd_flags(a0)       ; mark being online
  1663.  
  1664.  move.b  dd_rcr(a0),nic_rcr             ; set receiver to normal mode
  1665.  
  1666.  moveq   #S2EVENT_ONLINE,D0
  1667.  bsr     DoEvent                        ; return any ONLINE events
  1668.  
  1669. .done:
  1670.  move.l  (sp)+,a1
  1671.  bra     TermIO
  1672.  
  1673.  
  1674. .unconfigured:
  1675.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  1676.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1677.  bra.s   .error
  1678.  
  1679. .uninit:
  1680.  moveq   #S2WERR_UNIT_OFFLINE,d0
  1681.  move.b  #S2ERR_OUTOFSERVICE,io_error(a1)
  1682. .error:
  1683.  move.l  d0,ios2_wireerror(a1)
  1684.  bra.s   .done
  1685.  
  1686.  
  1687.  
  1688.  
  1689. ;==============================================
  1690. ;               S2_OFFLINE
  1691. ;==============================================
  1692. ;
  1693. ;           take device offline
  1694. ;
  1695. ;
  1696. devcmd_offline:
  1697.  bug     <"cnet: s2_offline",10>
  1698.  
  1699.  movem.l a1/a6,-(sp)
  1700.  move.l  io_device(a1),a0               ; a0 = device
  1701.  bset    #DDB_OFFLINE,dd_flags(a0)
  1702.  bclr    #DDB_ONLINE,dd_flags(a0)       ; already offline ?
  1703.  beq.s   .done
  1704.  
  1705.  btst    #DDB_NICUP,dd_flags(a0)
  1706.  beq.s   .nicoff
  1707.  move.b  #DSRC_MON,nic_rcr              ; set receiver to monitor mode
  1708. .nicoff:
  1709.  
  1710.  move.l  exec_base(pc),a6
  1711.  bug     <"cnet: s2_offline **NOT** aborting read/readorphan/write requests!",10>
  1712.  ifgt    0
  1713.  MYDISABLE
  1714. ; a0=device
  1715.  moveq   #S2ERR_OUTOFSERVICE,d0
  1716.  moveq   #S2WERR_UNIT_OFFLINE,d1
  1717.  bsr     AbortRW
  1718.  MYENABLE
  1719.  endc
  1720.  
  1721.  moveq   #S2EVENT_OFFLINE,d0
  1722.  bsr     DoEvent                        ; return any OFFLINE events
  1723.  
  1724. .done:
  1725.  movem.l (sp)+,a1/a6
  1726.  bra     TermIO
  1727.  
  1728.  
  1729.  
  1730. ;==============================================
  1731. ;               S2_ONEVENT
  1732. ;==============================================
  1733. ;
  1734. ;         queue up event requests
  1735. ;
  1736. ;  online/offline return immediately if the conditon is met.
  1737. ;
  1738. devcmd_onevent:
  1739.  bug     <"cnet: s2_onevent mask $%08lx",10>,ios2_wireerror(a1)
  1740.  
  1741.  movem.l a1/a3/a6,-(sp)
  1742.  move.l  io_device(a1),a3            ; a3 = device
  1743.  
  1744. ; do we know the requested events?
  1745.  move.l  ios2_wireerror(a1),d0
  1746.  and.l   #~(S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE),d0
  1747.  bne     .unknown
  1748.  
  1749.  move.l  ios2_wireerror(a1),d0
  1750.  and.l   #S2EVENT_ONLINE,d0          ; waiting for online event ?
  1751.  beq.s   .noton
  1752.  btst    #DDB_ONLINE,dd_flags(a3)    ; currently online ?
  1753.  bne.s   .rtn
  1754.  bra.s   .queue
  1755.  
  1756. .noton:
  1757.  move.l  ios2_wireerror(a1),d0
  1758.  and.l   #S2EVENT_OFFLINE,d0         ; waiting for offline event ?
  1759.  beq.s   .queue
  1760.  btst    #DDB_ONLINE,dd_flags(a3)    ; currently offline ?
  1761.  bne.s   .queue
  1762.  
  1763. .rtn:
  1764.  bug     <"is (on|off)line",10>
  1765.  move.l  d0,ios2_wireerror(a1)       ; return immediately
  1766. ;already! clr.b   io_error(a1)
  1767. .term:
  1768.  bsr     TermIO
  1769.  bra.s   .done
  1770.  
  1771. .queue:
  1772.  bug     <"queued",10>
  1773.  bclr    #IOB_QUICK,io_flags(a1)     ; must be queued
  1774.  move.l  exec_base(pc),a6
  1775.  lea     dd_eventlist(a3),a0
  1776.  MYDISABLE
  1777.  ADDTAIL                             ; add ioreq to event queue
  1778.  MYENABLE
  1779.  
  1780. .done:
  1781.  movem.l (sp)+,a1/a3/a6
  1782.  rts
  1783.  
  1784. .unknown:
  1785.  bug     <"unknown events requested!",10>
  1786.  moveq   #S2WERR_BAD_EVENT,d0
  1787.  move.b  #S2ERR_NOT_SUPPORTED,io_error(a1)
  1788.  move.l  d0,ios2_wireerror(a1)
  1789.  bra.s   .term
  1790.  
  1791.  
  1792.  
  1793. ;==============================================
  1794. ;             S2_DEVICEQUERY
  1795. ;==============================================
  1796. ;
  1797. devcmd_devicequery:
  1798.  bug     <"cnet: s2_devicequery",10>
  1799.  
  1800.  move.l  a1,-(sp)
  1801.  move.l  ios2_statdata(a1),a0    ; a0 = caller's buffer
  1802.  move.l  (a0),d1                 ; d1 = buffer size
  1803.  move.l  size_supplied(pc),d0
  1804.  cmp.l   d0,d1                   ; enough space to store info?
  1805.  bhs.s   .get
  1806.  
  1807.  clr.l   S2DQ_SIZESUPPLIED(a0)   ; nope!
  1808. .bad:
  1809.  moveq   #S2WERR_BAD_STATDATA,d0
  1810.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a1)
  1811.  move.l  d0,ios2_wireerror(a1)
  1812.  bra.s   .done
  1813.  
  1814. .get:
  1815.  lea     S2DQ_SIZESUPPLIED(a0),a1
  1816.  lea     size_supplied(pc),a0
  1817.  
  1818.  subq.l  #4,d0                   ; skip bytes_available
  1819.  bra.s   .copy
  1820. .copyloop:
  1821.  move.b  (a0)+,(a1)+             ; copy info to caller's buffer
  1822. .copy:
  1823.  subq.w  #1,d0
  1824.  bpl.s   .copyloop
  1825.  
  1826. .done:
  1827.  move.l  (sp)+,a1
  1828.  bra     TermIO
  1829.  
  1830.  
  1831.  
  1832. ;==============================================
  1833. ;           S2_GETSTATIONADDRESS
  1834. ;==============================================
  1835. ;
  1836. devcmd_getstationaddress:
  1837.  bug     <"cnet: s2_getstationaddress",10>
  1838.  
  1839.  move.l  io_device(a1),a0
  1840.  move.l  a1,-(sp)
  1841.  lea     dd_stationaddress(a0),a0
  1842.  lea     ios2_srcaddr(a1),a1     ; source address = station address
  1843.  bsr.s   .makeit
  1844.  subq.l  #ETHER_ADDR_SIZE,a0     ; dest address = default address
  1845.  bsr.s   .makeit
  1846.  
  1847.  move.l  (sp)+,a1
  1848.  bra     TermIO
  1849.  
  1850. .makeit:
  1851.  move.l  (a0)+,(a1)+
  1852.  move.w  (a0)+,(a1)+
  1853.  clr.w   (a1)+
  1854.  clr.l   (a1)+
  1855.  clr.l   (a1)+
  1856.  rts
  1857.  
  1858.  
  1859.  
  1860. ;==============================================
  1861. ;             S2_CONFIGINTERFACE
  1862. ;==============================================
  1863. ;
  1864. ; NOTE: a default station address has already
  1865. ;       been set by init_nic
  1866. ;
  1867. devcmd_configinterface:
  1868.  bug     <"cnet: s2_configinterface",10>
  1869.  
  1870.  move.l  io_device(a1),a0
  1871.  bset    #DDB_CONFIGURED,dd_flags(a0)   ; already configured ?
  1872.  bne     .already
  1873.  
  1874.  move.l  a6,-(sp)
  1875.  move.l  exec_base(pc),a6
  1876.  MYDISABLE
  1877.  
  1878.  move.l  ios2_srcaddr(a1),d0
  1879.  ble     .badaddr                       ; check for valid address
  1880.  
  1881.  lea     dd_stationaddress(a0),a0
  1882.  move.l  d0,(a0)
  1883.  move.w  ios2_srcaddr+4(a1),4(a0)
  1884.  
  1885.  move.b  nic_cr,d1                      ; remember current command
  1886.  delay
  1887.  move.b  #DSCM_NODMA|DSCM_PG1,nic_cr    ; select bank 1
  1888.  delay
  1889.  move.b  (a0)+,nic_par0
  1890.  delay
  1891.  move.b  (a0)+,nic_par1
  1892.  delay
  1893.  move.b  (a0)+,nic_par2
  1894.  delay                                  ; set station address
  1895.  move.b  (a0)+,nic_par3
  1896.  delay
  1897.  move.b  (a0)+,nic_par4
  1898.  delay
  1899.  move.b  (a0),nic_par5
  1900.  delay
  1901.  move.b  d1,nic_cr                      ; restore command
  1902.  
  1903. .done:
  1904.  MYENABLE
  1905.  move.l  (sp)+,a6
  1906. .termit:
  1907.  bra     TermIO
  1908.  
  1909. .badaddr:
  1910.  bclr    #DDB_CONFIGURED,dd_flags(a0)   ; NOT configured!
  1911.  moveq   #S2WERR_SRC_ADDRESS,d0         ; error, source address bad
  1912.  move.b  #S2ERR_BAD_ADDRESS,io_error(a1)
  1913.  move.l  d0,ios2_wireerror(a1)
  1914.  bra.s   .done
  1915.  
  1916. .already
  1917.  moveq   #S2WERR_IS_CONFIGURED,d0       ; error, already configured
  1918.  move.b  #S2ERR_BAD_STATE,io_error(a1)
  1919.  move.l  d0,ios2_wireerror(a1)
  1920.  bra.s   .termit
  1921.  
  1922.  
  1923.  
  1924. ;==============================================
  1925. ;              S2_MULTICAST
  1926. ;==============================================
  1927. ;
  1928. devcmd_multicast:
  1929.  bug     <"cnet: s2_multicast %08lx%04x",10>,ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  1930.  
  1931.  btst    #0,ios2_dstaddr(a1)      ; is dest a multicast address ?
  1932.  bne     devcmd_write
  1933.  
  1934.  move.l  a1,-(sp)
  1935.  moveq   #S2EVENT_TX,d0           ; return any TX events
  1936.  bsr     DoEvent
  1937.  move.l  (sp)+,a1
  1938.  
  1939.  moveq   #S2WERR_BAD_MULTICAST,d0 ; wasn't a multicast addr
  1940.  move.b  #S2ERR_BAD_ADDRESS,io_error(a1)
  1941.  move.l  d0,ios2_wireerror(a1)
  1942.  bra     TermIO
  1943.  
  1944.  
  1945.  
  1946. ;==============================================
  1947. ;              S2_BROADCAST
  1948. ;==============================================
  1949. ;
  1950. devcmd_broadcast:
  1951.  bug     <"cnet: s2_broadcast",10>
  1952.  
  1953.  moveq   #-1,d0
  1954.  move.l  d0,ios2_dstaddr+0(a1)    ; dest address = BROADCAST (255)
  1955.  move.w  d0,ios2_dstaddr+4(a1)    ; dest address = BROADCAST (255)
  1956.  
  1957.  bra     devcmd_write
  1958.  
  1959.  
  1960.  
  1961. ;============================================
  1962. ;              S2_TRACKTYPE
  1963. ;============================================
  1964. ;
  1965. ; This function adds a packet type to the
  1966. ; list of those that are being tracked.
  1967. ;
  1968. devcmd_tracktype:
  1969.  bug     <"cnet: s2_tracktype %ld",10>,ios2_packettype(a1)
  1970.  
  1971.  movem.l a2/a3/a6,-(sp)
  1972.  move.l  exec_base(pc),a6
  1973.  move.l  a1,a2                         ; a2 = ioreq
  1974.  move.l  io_device(a1),a3
  1975.  move.l  ios2_packettype(a2),d0        ; d0 = our packet type
  1976.  
  1977.  MYDISABLE                             ; lock access to list
  1978.  move.l  dd_tracklist(a3),a0           ; a0 = 1st entry in list
  1979.  bra.s   .start
  1980.  
  1981. .search:
  1982.  cmp.l   ss2_ptype(a0),d0              ; = our packet type ?
  1983.  beq.s   .duperr
  1984.  move.l  d1,a0
  1985. .start:
  1986.  move.l  (a0),d1
  1987.  bne.s   .search                       ; end of list ?
  1988.  
  1989.  moveq   #ss2_sizeof,d0
  1990.  move.l  #MEMF_PUBLIC|MEMF_CLEAR,d1
  1991.  jsr     _LVOAllocMem(a6)              ; allocmem for tracking node
  1992.  tst.l   d0
  1993.  beq.s   .nomem
  1994.  
  1995.  move.l  d0,a1                              ; a1 = new entry
  1996.  move.l  ios2_packettype(a2),ss2_ptype(a1)  ; set tracking type
  1997.  lea     dd_tracklist(a3),a0
  1998.  ADDTAIL                                    ; add new tracktype node to list
  1999.  
  2000. .done:
  2001.  MYENABLE                              ; release lock on lists
  2002.  move.l  a2,a1
  2003.  movem.l (sp)+,a2/a3/a6
  2004.  bra     TermIO
  2005.  
  2006.  
  2007. .nomem:
  2008.  moveq   #S2WERR_NOT_TRACKED,d0
  2009.  move.b  #S2ERR_NO_RESOURCES,io_error(a2)
  2010.  bra.s   .error                        ; error, can't allocate memory!
  2011.  
  2012. .duperr:
  2013.  moveq   #S2WERR_ALREADY_TRACKED,d0
  2014.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2015.  
  2016. .error:
  2017.  move.l  d0,ios2_wireerror(a2)         ; error, type is tracked already!
  2018.  bra.s   .done
  2019.  
  2020.  
  2021.  
  2022. ;==============================================
  2023. ;             S2_UNTRACKTYPE
  2024. ;==============================================
  2025. ;
  2026. ; This function removes a packet type from the
  2027. ; list of those that are being tracked.
  2028. ;
  2029. devcmd_untracktype:
  2030.  bug     <"cnet: s2_untracktype %ld",10>,ios2_packettype(a1)
  2031.  
  2032.  movem.l a2-a3/a6,-(sp)
  2033.  move.l  exec_base(pc),a6
  2034.  move.l  a1,a2                  ; a2 = ioreq
  2035.  move.l  io_device(a1),a0
  2036.  move.l  ios2_packettype(a2),d0 ; d0 = packet type to untrack
  2037.  
  2038.  MYDISABLE                      ; lock access to list
  2039.  move.l  dd_tracklist(a0),a3    ; a3 = 1st entry in tracking list
  2040.  bra.s   .start
  2041.  
  2042. .search:
  2043.  cmp.l   ss2_ptype(a3),d0       ; found our packet type ?
  2044.  beq.s   .found
  2045.  move.l  d1,a3                  ; a3 = next entry
  2046. .start:
  2047.  move.l  (a3),d1
  2048.  bne.s   .search                ; end of list?
  2049.  bra.s   .error
  2050.  
  2051. .found:
  2052.  move.l  a3,a1
  2053.  REMOVE                         ; remove entry from list
  2054.  move.l  a3,a1
  2055.  moveq   #ss2_sizeof,d0
  2056.  jsr     _LVOFreeMem(a6)        ; free entry's memory
  2057.  
  2058. .done:
  2059.  MYENABLE                      ; unlock access to list
  2060.  move.l  a2,a1
  2061.  movem.l (sp)+,a2-a3/a6
  2062.  bra     TermIO
  2063.  
  2064.  
  2065. .error:
  2066.  moveq   #S2WERR_NOT_TRACKED,d0        ; error, no tracktype!
  2067.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2068.  move.l  d0,ios2_wireerror(a2)
  2069.  bra.s   .done
  2070.  
  2071.  
  2072.  
  2073. ;==================================================
  2074. ;               S2_GETTYPESTATS
  2075. ;==================================================
  2076. ; This function returns statistics for a specific
  2077. ; type of packet that is being tracked.
  2078. ;
  2079. devcmd_gettypestats:
  2080.  bug     <"cnet: s2_gettypestats",10>
  2081.  
  2082.  movem.l a2/a6,-(sp)
  2083.  move.l  exec_base(pc),a6
  2084.  move.l  a1,a2                       ; a2 = ioreq
  2085.  move.l  io_device(a1),a0
  2086.  move.l  ios2_packettype(a2),d0      ; d0 = packettype
  2087.  
  2088.  MYDISABLE                           ; lock access to list
  2089.  move.l  dd_tracklist(a0),a0         ; a0 = 1st entry in tracking list
  2090.  bra.s   .start
  2091.  
  2092. .loop:
  2093.  move.l  d1,a0                       ; a0  = next entry
  2094. .start:
  2095.  move.l  (a0),d1                     ; end of list ?
  2096.  beq.s   .notfound
  2097.  cmp.l   ss2_ptype(a0),d0            ; found our track type ?
  2098.  bne.s   .loop
  2099.  
  2100. ; note that both ss2_stats and ios2_statdata are quaranteed to be
  2101. ; word aligned.
  2102.  lea     ss2_stats(a0),a0
  2103.  move.l  ios2_statdata(a2),a1
  2104.  moveq   #s2pts_size/4,d0
  2105. .copystats
  2106.  move.l  (a0)+,(a1)+                 ; copy stats to ioreq
  2107.  subq.l  #1,d0
  2108.  bne.s   .copystats
  2109.  
  2110. .done:
  2111.  MYENABLE                            ; release lock on list
  2112.  move.l  a2,a1
  2113.  movem.l (sp)+,a2/a6
  2114.  bra     TermIO
  2115.  
  2116. .notfound:
  2117.  moveq   #S2WERR_NOT_TRACKED,d0
  2118.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2119.  move.l  d0,ios2_wireerror(a2)       ; error, couldn't find track type
  2120.  bra.s   .done
  2121.  
  2122.  
  2123.  
  2124. ;==============================================
  2125. ;            S2_GETSPECIALSTATS
  2126. ;==============================================
  2127. ;
  2128. devcmd_getspecialstats:
  2129.  bug     <"cnet: s2_getspecialstats",10>
  2130.  
  2131.  movem.l a1-a2,-(sp)
  2132.  move.l  io_device(a1),a2                    ; a2 = unit
  2133.  move.l  ios2_statdata(a1),a1
  2134.  clr.l   s2ssh_recordcountsupplied(a1)
  2135.  move.l  (a1)+,d0                            ; check s2ssh_recordcountmax
  2136.  beq.s   .done
  2137.  
  2138.  addq.l  #1,(a1)+                            ; s2ssh_recordcountsupplied++
  2139.  move.l  a1,a0
  2140.  move.l  #S2SS_ETHERNET_BADMULTICAST,(a0)+   ; set type      }
  2141.  move.l  dd_badmulticasts(a2),(a0)+          ; set statistic } bad multi
  2142.  move.l  #multiname,(a0)+                    ; set name      }
  2143.  subq.l  #1,d0
  2144.  beq.s   .done                               ; want more ?
  2145.  
  2146.  addq.l  #1,-(a1)                            ; s2ssh_recordcountsupplied++
  2147.  move.l  #S2SS_ETHERNET_RETRIES,(a0)+        ; set type      }
  2148.  move.l  dd_retries(a2),(a0)+                ; set statistic } retries
  2149.  move.l  #retryname,(a0)+                    ; set name      }
  2150.  
  2151. .done:
  2152.  movem.l (sp)+,a1-a2
  2153.  bra     TermIO
  2154.  
  2155.  
  2156.  
  2157. ;==============================================
  2158. ;           S2_GETGLOBALSTATS
  2159. ;==============================================
  2160. ;
  2161. devcmd_getglobalstats:
  2162.  bug     <"cnet: s2_getglobalstats",10>
  2163.  
  2164.  move.l  a1,-(sp)
  2165.  move.l  io_device(a1),a0
  2166.  
  2167. ; note that both dd_devicestats and ios2_statdata are quaranteed to be
  2168. ; word aligned.
  2169. ;
  2170.  lea     dd_devicestats(a0),a0
  2171.  move.l  ios2_statdata(a1),a1
  2172.  moveq   #s2ds_size/4,d0
  2173. .copy:
  2174.  move.l  (a0)+,(a1)+             ; get sana2devicestats
  2175.  subq.l  #1,d0
  2176.  bne.s   .copy
  2177.  
  2178.  move.l  (sp)+,a1
  2179.  bra     TermIO
  2180.  
  2181.  
  2182.  
  2183. ;==========================================================
  2184. ;                        get_time
  2185. ;==========================================================
  2186. ;
  2187. ;  in: a0 = pointer to timeval struct
  2188. ;
  2189. ;   get current time_of_day
  2190. ;
  2191. get_time:
  2192.  move.l  timereq+io_device(pc),d0
  2193.  movem.l a2/a6,-(sp)
  2194.  beq.s   .open                   ; io_device <> 0 ?
  2195.  addq.l  #1,d0
  2196.  move.l  a0,a2
  2197.  bne.s   .gotdev                 ; io_device <> -1 ?
  2198. .open:
  2199.  move.l  exec_base(pc),a6
  2200.  lea     timerdevname(pc),a0
  2201.  lea     timereq(pc),a1
  2202.  moveq   #UNIT_VBLANK,d0
  2203.  move.b  #NT_MESSAGE,ln_type(a1)
  2204.  moveq   #0,d1
  2205.  move.w  #iotv_size,mn_length(a1)
  2206.  jsr     _LVOOpenDevice(a6)
  2207.  tst.l   d0
  2208.  bne.s   .done
  2209.  
  2210. .gotdev:
  2211.  lea     timereq(pc),a1
  2212.  move.l  io_device(a1),a6
  2213.  move.l  a2,a0
  2214.  jsr     _LVOGetSysTime(a6)
  2215. .done:
  2216.  movem.l (sp)+,a2/a6
  2217.  rts
  2218.  
  2219.  
  2220.  
  2221. ;==============================================
  2222. ;              S2_ADDMULTICASTADDRESS
  2223. ;==============================================
  2224. ;
  2225. devcmd_addmulticast:
  2226.  bug     <"cnet: s2_addmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
  2227.  
  2228.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower = upper !
  2229.  move.l  ios2_srcaddr(a1),-(sp)
  2230.  move.l  ios2_srcaddr+4(a1),-(sp)
  2231.  move.l  ios2_srcaddr(a1),-(sp)
  2232.  
  2233. addmcast:
  2234.  movem.l a2-a4/a6,-(sp)
  2235.  move.l  a6,a3                       ; a3 = device
  2236.  move.l  exec_base(pc),a6
  2237.  move.l  a1,a4                       ; a4 = ioreq
  2238.  
  2239.  bsr.s   addmcastrange
  2240.  
  2241.  move.l  a4,a1
  2242.  movem.l (sp)+,a2-a4/a6
  2243.  lea     4*4(sp),sp
  2244.  bra     TermIO
  2245.  
  2246.  
  2247.  
  2248. ;==============================================
  2249. ;              S2_ADDMULTICASTADDRESSES
  2250. ;==============================================
  2251. ;
  2252. devcmd_addmulticasts:
  2253.  bug     <"cnet: s2_addmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  2254.  
  2255.  move.l  ios2_dstaddr+4(a1),-(sp)    ; upper
  2256.  move.l  ios2_dstaddr(a1),-(sp)
  2257.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower
  2258.  move.l  ios2_srcaddr(a1),-(sp)
  2259.  bra.s   addmcast
  2260.  
  2261.  
  2262.  
  2263.  
  2264. AMCRO    EQU 4+(4*4)
  2265. addmcastrange:
  2266.  btst    #0,AMCRO+0+0(sp)            ; is src a multicast address ?
  2267.  beq.s   .badmcast
  2268.  btst    #0,AMCRO+8+0(sp)            ; is dst a multicast address ?
  2269.  beq.s   .badmcast
  2270.  
  2271.  lea     dd_multicastssema(a3),a0
  2272.  jsr     _LVOObtainSemaphore(a6)     ; lock access to list
  2273.  move.l  dd_multicasts(a3),a0        ; a0 = first entry in multicast list
  2274.  bra.s   .getmulti
  2275.  
  2276. .check:
  2277.  move.l  AMCRO+0+0(sp),d0
  2278.  cmp.l   mcastar_loweraddr(a0),d0
  2279.  bne.s   .next
  2280.  move.w  AMCRO+0+4(sp),d0
  2281.  cmp.w   mcastar_loweraddr+4(a0),d0
  2282.  bne.s   .next
  2283.  move.l  AMCRO+8+0(sp),d0            ; is our address in an existing entry ?
  2284.  cmp.l   mcastar_upperaddr(a0),d0
  2285.  bne.s   .next                       
  2286.  move.w  AMCRO+8+4(sp),d0
  2287.  cmp.w   mcastar_upperaddr+4(a0),d0
  2288.  bne.s   .next
  2289.  
  2290.  addq.l  #1,mcastar_count(a0)        ; added same address again
  2291.  ifd     debug
  2292.  move.l  mcastar_count(a0),d0
  2293.  bug     <"cnet: mcast node $%lx count=%ld",10>,a0,d0
  2294.  endc
  2295.  bra     .unlock
  2296.  
  2297. .next:
  2298.  move.l  d1,a0                       ; get next node in list
  2299. .getmulti:
  2300.  move.l  (a0),d1                     ; end of list ?
  2301.  bne.s   .check
  2302.  
  2303.  moveq   #mcastar_sizeof,d0
  2304.  move.l  #MEMF_PUBLIC|MEMF_CLEAR,d1
  2305.  jsr     _LVOAllocMem(a6)            ; allocate memory for multicast entry
  2306.  tst.l   d0
  2307.  beq.s   .nomem
  2308.  
  2309.  move.l  d0,a1                                  ; a1 = new entry
  2310.  move.w  #1,mcastar_count+2(a1)                 ; count = 1
  2311.  move.l  AMCRO+0+0(sp),mcastar_loweraddr(a1)
  2312.  move.w  AMCRO+0+4(sp),mcastar_loweraddr+4(a1)
  2313.  move.l  AMCRO+8+0(sp),mcastar_upperaddr(a1)
  2314.  move.w  AMCRO+8+4(sp),mcastar_upperaddr+4(a1)
  2315.  bug     <"cnet: new mcast node at $%08lx",10>,a1
  2316.  lea     dd_multicasts(a3),a0
  2317.  ADDTAIL                                        ; add to list
  2318.  move.l  a3,a0
  2319.  bsr     update_multicasts                      ; update multicasts in nic
  2320.  
  2321. .unlock
  2322.  lea     dd_multicastssema(a3),a0
  2323.  jmp     _LVOReleaseSemaphore(a6)    ; release lock on list
  2324.  
  2325.  
  2326. .badmcast:
  2327.  moveq   #S2WERR_BAD_MULTICAST,d0
  2328.  move.b  #S2ERR_BAD_ADDRESS,io_error(a4)
  2329.  move.l  d0,ios2_wireerror(a4)       ; invalid multicast address
  2330.  rts
  2331.  
  2332.  
  2333. .nomem:
  2334.  moveq   #S2WERR_GENERIC_ERROR,d0
  2335.  move.b  #S2ERR_NO_RESOURCES,io_error(a4)
  2336.  move.l  d0,ios2_wireerror(a4)
  2337.  bra.s   .unlock
  2338.  
  2339.  
  2340.  
  2341. ;==============================================
  2342. ;              S2_DELMULTICASTADDRESS
  2343. ;==============================================
  2344. ;
  2345. devcmd_delmulticast:
  2346.  bug     <"cnet: s2_delmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
  2347.  
  2348.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower = upper !
  2349.  move.l  ios2_srcaddr(a1),-(sp)
  2350.  move.l  ios2_srcaddr+4(a1),-(sp)
  2351.  move.l  ios2_srcaddr(a1),-(sp)
  2352.  
  2353. remmcast:
  2354.  movem.l a2-a4/a6,-(sp)
  2355.  move.l  a6,a3                       ; a3 = device
  2356.  move.l  exec_base(pc),a6
  2357.  move.l  a1,a4                       ; a4 = ioreq
  2358.  
  2359.  bsr.s   delmcastrange
  2360.  
  2361.  move.l  a4,a1
  2362.  movem.l (sp)+,a2-a4/a6
  2363.  lea     4*4(sp),sp
  2364.  bra     TermIO
  2365.  
  2366.  
  2367.  
  2368. ;==============================================
  2369. ;              S2_DELMULTICASTADDRESSES
  2370. ;==============================================
  2371. ;
  2372. devcmd_delmulticasts:
  2373.  bug     <"cnet: s2_delmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  2374.  
  2375.  move.l  ios2_dstaddr+4(a1),-(sp)    ; upper
  2376.  move.l  ios2_dstaddr(a1),-(sp)
  2377.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower
  2378.  move.l  ios2_srcaddr(a1),-(sp)
  2379.  bra.s   remmcast
  2380.  
  2381.  
  2382.  
  2383. DMCRO    EQU 4+(4*4)
  2384. delmcastrange:
  2385.  lea     dd_multicastssema(a3),a0
  2386.  jsr     _LVOObtainSemaphore(a6)     ; lock access to list
  2387.  move.l  dd_multicasts(a3),a2        ; a2 = first entry in multicast list
  2388.  bra.s   .getmulti
  2389.  
  2390. .check:
  2391.  move.l  DMCRO+0+0(sp),d0
  2392.  cmp.l   mcastar_loweraddr(a2),d0
  2393.  bne.s   .next
  2394.  move.w  DMCRO+0+4(sp),d0
  2395.  cmp.w   mcastar_loweraddr+4(a2),d0
  2396.  bne.s   .next
  2397.  move.l  DMCRO+8+0(sp),d0            ; is it our address ?
  2398.  cmp.l   mcastar_upperaddr(a2),d0
  2399.  bne.s   .next
  2400.  move.w  DMCRO+8+4(sp),d0
  2401.  cmp.w   mcastar_upperaddr+4(a2),d0
  2402.  bne.s   .next
  2403.  
  2404.  subq.l  #1,mcastar_count(a2)        ; one less count
  2405.  bne.s   .done
  2406.  
  2407.  bug     <"cnet: mcast entry $%08lx removed",10>,a2
  2408.  move.l  a2,a1
  2409.  REMOVE                              ; remove entry from list
  2410.  move.l  a2,a1
  2411.  moveq   #mcastar_sizeof,d0
  2412.  jsr     _LVOFreeMem(a6)             ; free memory used by entry
  2413.  
  2414.  move.l  a3,a0
  2415.  bsr     update_multicasts           ; update multicasts in nic
  2416.  bra.s   .done
  2417.  
  2418. .next:
  2419.  move.l  d1,a2                       ; get next node in list
  2420. .getmulti:
  2421.  move.l  (a2),d1                     ; end of list ?
  2422.  bne.s   .check
  2423.  
  2424.  moveq   #S2WERR_BAD_MULTICAST,d0
  2425.  move.b  #S2ERR_BAD_STATE,io_error(a4)
  2426.  move.l  d0,ios2_wireerror(a4)
  2427.  
  2428. .done:
  2429.  lea     dd_multicastssema(a3),a0
  2430.  jmp     _LVOReleaseSemaphore(a6)    ; release lock on list
  2431.  
  2432.  
  2433.  
  2434.  
  2435. ;================================================================
  2436. ;                    Update Multicasts
  2437. ;================================================================
  2438. ;
  2439. ;  calculate multicast hash table and send it to nic
  2440. ;
  2441. ;  as of 1.2beta4 multicasts can be a address range, also single
  2442. ;  addresses are defined with lower = upper.
  2443. ;
  2444. ;   update_multicasts(device)
  2445. ;                       a0
  2446. update_multicasts:
  2447.  movem.l d2-d4/a2,-(sp)
  2448.  move.l  dd_multicasts(a0),a2
  2449.  lea     mcastaddr(pc),a0
  2450.  clr.l   (a0)+          ; clear all multicast bits
  2451.  clr.l   (a0)+
  2452.  
  2453.  subq.l  #8,sp          ; temp for address
  2454.  
  2455. .next:
  2456.  move.l  (a2),d4
  2457.  beq.s   .update        ; end of list ?
  2458.  move.l  mcastar_loweraddr(a2),(sp)
  2459.  move.w  mcastar_loweraddr+4(a2),4(sp)
  2460.  
  2461. .hashall:
  2462.  moveq   #-1,d0                 ; initial crc seed
  2463.  moveq   #6,d1                  ; 6 bytes in ethernet address
  2464.  move.l  sp,a0                  ; data to crc
  2465.  
  2466. .nextbyte:
  2467.  move.b  (a0)+,d3        ; get next data byte
  2468.  moveq   #8,d2           ; 8 bits in byte
  2469.  
  2470. .nextbit:
  2471.  lsl.l   #1,d0           ; crc << 1
  2472.  bcc.s   .crcnot1
  2473.  lsr.b   #1,d3           ; data >> 1
  2474.  bcc.s   .xor
  2475.  bra.s   .skipnext
  2476. .crcnot1:
  2477.  lsr.b   #1,d3           ; data >> 1
  2478.  bcc.s   .skipnext
  2479. .xor:
  2480.  eor.l   #$04c11db7,d0   ; crc = crc XOR polynomial
  2481. .skipnext:
  2482.  subq.l  #1,d2
  2483.  bne.s   .nextbit
  2484.  
  2485.  subq.l  #1,d1
  2486.  bne.s   .nextbyte
  2487.  
  2488.  rol.l   #6,d0
  2489.  lea     mcastaddr(pc),a0
  2490.  and.w   #%0000000000111111,d0  ; isolate upper 6 bits
  2491.  move.w  d0,d1
  2492.  and.b   #%00000111,d0          ; d0 = bit in byte
  2493.  lsr.w   #3,d1                  ; d1 = byte offset
  2494.  bset    d0,0(a0,d1.w)          ; set bit for hashed multicast address
  2495.  
  2496.  
  2497.  move.l  mcastar_upperaddr+2(a2),d0
  2498.  move.w  mcastar_upperaddr(a2),d1
  2499.  cmp.l   2(sp),d0       ; all done with this range ?
  2500.  bne.b   .still
  2501.  cmp.w   (sp),d1
  2502.  beq.b   .donext        ; all done with this range ?
  2503. .still:
  2504. ; increment to next address...
  2505.  addq.l  #1,2(sp)
  2506.  bne.b   .hashall       ; did we overflow 32bit ?
  2507.  addq.w  #1,(sp)        ; 48bit add fix
  2508.  bra.s   .hashall
  2509.  
  2510. .donext:
  2511.  move.l  d4,a2
  2512.  bra.s   .next
  2513.  
  2514. .update:
  2515.  addq.l  #8,sp
  2516.  
  2517.  bsr     put_multi      ; update multicast bits in nic
  2518.  
  2519.  movem.l (sp)+,d2-d4/a2
  2520.  rts
  2521.  
  2522.  
  2523.  
  2524.  
  2525.  ifgt    0  ; this stuff inlined
  2526.  
  2527. ;==============================================================
  2528. ;                 hash multicast address
  2529. ;==============================================================
  2530. ; The nic does not compare multicast addresses directly, but
  2531. ; instead uses a bitfield of 64 bits - each bit corresponds
  2532. ; to a 6 bit hash code for the multicast address. If the bit
  2533. ; is set then any multicast address that matches the hash code
  2534. ; will be accepted.
  2535. ;
  2536. ; The hash code is generated by taking the upper 6 bits of the
  2537. ; 32 bit crc of the multicast address.
  2538. ;
  2539. ;  hash_multi(address)
  2540. ;               a0
  2541. ;
  2542. hash_multi:
  2543.  moveq   #-1,d0                 ; initial crc seed
  2544.  moveq   #6,d1                  ; 6 bytes in ethernet address
  2545.  
  2546.  bsr.s   calc_crc               ; calculate crc for this multicast address
  2547.  
  2548.  rol.l   #6,d0
  2549.  lea     mcastaddr(pc),a0
  2550.  and.w   #%0000000000111111,d0  ; isolate upper 6 bits
  2551.  move.w  d0,d1
  2552.  and.b   #%00000111,d0          ; d0 = bit in byte
  2553.  lsr.w   #3,d1                  ; d1 = byte offset
  2554.  bset    d0,0(a0,d1.w)          ; set bit for hashed multicast address
  2555.  rts
  2556.  
  2557.  
  2558.  
  2559. ;===========================================================================
  2560. ;                          Calculate 32 bit crc
  2561. ;===========================================================================
  2562. ;
  2563. ; - for each bit: if (crcbit=1 XOR databit=1) then crc=(crc XOR polynomial).
  2564. ; - polynomial is correct when data bits range 0-x, crc bits range 31-0.
  2565. ; - crc wraps at 32 bits.
  2566. ;
  2567. ;  crc = calc_crc(data, seed, bytelength)
  2568. ;   d0.l           a0    d0.l     d1.l
  2569. ;
  2570. calc_crc:
  2571.  movem.l d2/d3,-(sp)
  2572.  
  2573. .nextbyte:
  2574.  move.b  (a0)+,d3        ; get next data byte
  2575.  moveq   #8,d2           ; 8 bits in byte
  2576.  
  2577. .nextbit:
  2578.  lsl.l   #1,d0           ; crc << 1
  2579.  bcc.s   .crcnot1
  2580.  lsr.b   #1,d3           ; data >> 1
  2581.  bcc.s   .xor
  2582.  bra.s   .next
  2583. .crcnot1:
  2584.  lsr.b   #1,d3           ; data >> 1
  2585.  bcc.s   .next
  2586. .xor:
  2587.  eor.l   #$04c11db7,d0   ; crc = crc XOR polynomial
  2588. .next:
  2589.  subq.l  #1,d2
  2590.  bne.s   .nextbit
  2591.  
  2592.  subq.l  #1,d1
  2593.  bne.s   .nextbyte
  2594.  
  2595.  movem.l (sp)+,d2/d3
  2596.  rts
  2597.  
  2598.  endc
  2599.  
  2600.  
  2601.  
  2602. ;==============================================================
  2603. ;      Put Multicast address bitfield into NIC registers
  2604. ;==============================================================
  2605. ;
  2606. put_multi:
  2607.  move.l  a6,-(sp)
  2608.  move.l  exec_base(pc),a6
  2609.  lea     mcastaddr(pc),a0
  2610.  MYDISABLE
  2611.  delay
  2612.  move.b  nic_cr,d0            ; save old command
  2613.  delay
  2614.  move.b  #DSCM_PG1|DSCM_NODMA|DSCM_STOP,nic_cr ; select page 1
  2615.  delay
  2616.  move.b  (a0)+,nic_mar0
  2617.  delay
  2618.  move.b  (a0)+,nic_mar1
  2619.  delay
  2620.  move.b  (a0)+,nic_mar2
  2621.  delay
  2622.  move.b  (a0)+,nic_mar3
  2623.  delay                        ; put Multicast bits
  2624.  move.b  (a0)+,nic_mar4
  2625.  delay
  2626.  move.b  (a0)+,nic_mar5
  2627.  delay
  2628.  move.b  (a0)+,nic_mar6
  2629.  delay
  2630.  move.b  (a0),nic_mar7
  2631.  delay
  2632.  move.b  d0,nic_cr            ; restore old command
  2633.  MYENABLE
  2634.  move.l  (sp)+,a6
  2635.  rts
  2636.  
  2637.  
  2638.  
  2639. ;=========================================================
  2640. ;              commands not supported
  2641. ;=========================================================
  2642. ;
  2643. devcmd_nosupport:
  2644.  bug     <"cnet: Unsupported command %d",10>,io_command-2(a1)
  2645.  
  2646.  moveq   #S2WERR_GENERIC_ERROR,d0
  2647.  move.b  #S2ERR_NOT_SUPPORTED,io_error(a1)
  2648.  move.l  d0,ios2_wireerror(a1)
  2649.  bra     TermIO
  2650.  
  2651.  
  2652.  
  2653. ;==========================================================
  2654. ;             doevent([device,] events)
  2655. ;                       a0       d0
  2656. ;==========================================================
  2657. ;
  2658. ; called when an 'important' event occurs
  2659. ;
  2660. DoEvent:
  2661.  bug     <"cnet: doevent $%08lx ...">,d0
  2662.  
  2663.  movem.l d2-d3/a2/a6,-(sp)
  2664.  move.l  exec_base(pc),a6
  2665.  move.l  d0,d2
  2666.  move.l  me_myself(pc),a0        ; get global pointer to self...
  2667.  MYDISABLE                       ; lock eventlist
  2668.  
  2669.  move.l  dd_eventlist(a0),a2     ; get first ioreq
  2670.  bra.s   .start
  2671.  
  2672. .loop:
  2673.  move.l  ios2_wireerror(a2),d0
  2674.  and.l   d2,d0                   ; ioreq for our events?
  2675.  beq.s   .next
  2676.  
  2677.  move.l  d0,ios2_wireerror(a2)   ; set the actual events
  2678.  move.l  a2,a1
  2679.  REMOVE                          ; remove ioreq from list
  2680.  move.b  #NT_REPLYMSG,ln_type(a2)
  2681.  move.l  a2,a1
  2682.  bug     <"cnet: returned eventreq $%lx",10>,a1
  2683.  jsr     _LVOReplyMsg(a6)        ; send reply to ioreq owner
  2684.  
  2685. .next:
  2686.  move.l  d3,a2                   ; next ioreq
  2687.  
  2688. .start:
  2689.  move.l  (a2),d3                 ; last ioreq ?
  2690.  bne.s   .loop
  2691.  
  2692.  MYENABLE                        ; unlock eventlist
  2693.  bug     <10,"cnet: doevent done",10>
  2694.  movem.l (sp)+,d2-d3/a2/a6
  2695.  rts
  2696.  
  2697.  
  2698.  
  2699. ;==================================================================
  2700. ;        RemoteRead(buffer, nicbuffer, length)
  2701. ;                     a1       d0.w     d1.w
  2702. ;==================================================================
  2703. ;
  2704. ; Get a copy of data stored in the network card's onboard RAM.
  2705. ;
  2706. ;  buffer     = Amiga RAM
  2707. ;
  2708. ;  nicbuffer  = 16 bit address in card memory
  2709. ;
  2710.  CNOP 0,4
  2711. ;RemoteRead:
  2712. REMOTEREAD MACRO
  2713.  
  2714.  ifd     turboio
  2715.  
  2716.  addq.w  #3,d1                   ; bump up count to even value
  2717.  and.w   #-4,d1
  2718.  delay
  2719.  swap    d1
  2720.  move.b  nic_cr,d1               ; save old command
  2721.  swap    d1
  2722.  delay
  2723.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  2724.  delay
  2725.  move.b  d1,nic_rbcr0            ;   set count.lo
  2726.  ror.w   #8,d1
  2727.  delay
  2728.  move.b  d1,nic_rbcr1            ;   set count.hi
  2729.  delay
  2730.  move.b  d0,nic_rsar0            ;   set address.lo
  2731.  ror.w   #8,d0
  2732.  delay
  2733.  move.b  d0,nic_rsar1            ;   set address.hi
  2734.  delay
  2735.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  2736.  ror.w   #8,d1
  2737.  move.w  d1,d0
  2738.  and.w   #%0000000000111100,d1
  2739.  lea     nic_data,a0
  2740.  lsr.w   #1,d1
  2741.  lsr.w   #6,d0
  2742.  neg.w   d1
  2743.  jmp     .rr_startread(pc,d1.w)
  2744. .rr_dmaread:
  2745.  move.l  (a0),(a1)+
  2746.  move.l  (a0),(a1)+
  2747.  move.l  (a0),(a1)+
  2748.  move.l  (a0),(a1)+
  2749.  move.l  (a0),(a1)+
  2750.  move.l  (a0),(a1)+
  2751.  move.l  (a0),(a1)+
  2752.  move.l  (a0),(a1)+
  2753.  move.l  (a0),(a1)+
  2754.  move.l  (a0),(a1)+
  2755.  move.l  (a0),(a1)+
  2756.  move.l  (a0),(a1)+
  2757.  move.l  (a0),(a1)+
  2758.  move.l  (a0),(a1)+
  2759.  move.l  (a0),(a1)+
  2760.  move.l  (a0),(a1)+
  2761. .rr_startread:
  2762.  subq.w  #1,d0
  2763.  bpl.s   .rr_dmaread
  2764.  
  2765.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete
  2766.  swap    d1
  2767.  delay
  2768.  move.b  d1,nic_cr               ; restore old command
  2769. ;rts
  2770.  
  2771.  else
  2772.  
  2773.  addq.w  #1,d1                   ; bump up count to even value
  2774.  and.w   #-2,d1
  2775.  delay
  2776.  swap    d1
  2777.  move.b  nic_cr,d1               ; save old command
  2778.  swap    d1
  2779.  delay
  2780.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  2781.  delay
  2782.  move.b  d1,nic_rbcr0            ;   set count.lo
  2783.  ror.w   #8,d1
  2784.  delay
  2785.  move.b  d1,nic_rbcr1            ;   set count.hi
  2786.  delay
  2787.  move.b  d0,nic_rsar0            ;   set address.lo
  2788.  ror.w   #8,d0
  2789.  delay
  2790.  move.b  d0,nic_rsar1            ;   set address.hi
  2791.  delay
  2792.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  2793.  ror.w   #8,d1
  2794.  move.w  d1,d0
  2795.  and.w   #%0000000000011110,d0
  2796.  lea     nic_data,a0
  2797.  neg.w   d0
  2798.  lsr.w   #5,d1
  2799.  jmp     .rr_startread(pc,d0.w)
  2800. .rr_dmaread:
  2801.  move.w  (a0),(a1)+
  2802.  move.w  (a0),(a1)+
  2803.  move.w  (a0),(a1)+
  2804.  move.w  (a0),(a1)+
  2805.  move.w  (a0),(a1)+
  2806.  move.w  (a0),(a1)+
  2807.  move.w  (a0),(a1)+
  2808.  move.w  (a0),(a1)+
  2809.  move.w  (a0),(a1)+
  2810.  move.w  (a0),(a1)+
  2811.  move.w  (a0),(a1)+
  2812.  move.w  (a0),(a1)+
  2813.  move.w  (a0),(a1)+
  2814.  move.w  (a0),(a1)+
  2815.  move.w  (a0),(a1)+
  2816.  move.w  (a0),(a1)+
  2817. .rr_startread:
  2818.  subq.w  #1,d1
  2819.  bpl.s   .rr_dmaread
  2820.  
  2821.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete
  2822.  swap    d1
  2823.  delay
  2824.  move.b  d1,nic_cr               ; restore old command
  2825. ;rts
  2826.  
  2827.  endc
  2828.  ENDM
  2829.  
  2830.  
  2831. ;=================================================================
  2832. ;         RemoteWrite( buffer, nicbuffer, count )
  2833. ;                        a1      d0.w     d1.w
  2834. ;=================================================================
  2835. ;
  2836. ;      Puts data into the network card's onboard RAM
  2837. ;
  2838. ;  buffer    = Amiga memory
  2839. ;
  2840. ;  nicbuffer = 16 bit address in card RAM
  2841. ;
  2842. ;
  2843.  CNOP 0,4
  2844. ;RemoteWrite:
  2845. REMOTEWRITE MACRO
  2846.  ifd     turboio
  2847.  
  2848.  addq.w  #3,d1
  2849.  and.w   #-4,d1                     ; bump up count to even value
  2850.  swap    d1
  2851.  delay
  2852.  move.b  nic_cr,d1                  ; save old command
  2853.  swap    d1
  2854.  delay
  2855.  move.b  #DSIS_RDC,nic_isr          ; remote DMA complete
  2856.  delay
  2857.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  2858.  delay
  2859.  move.b  d0,nic_rsar0               ; set address.lo
  2860.  lsr.w   #8,d0
  2861.  delay
  2862.  move.b  d0,nic_rsar1               ; set address.hi
  2863.  delay
  2864.  move.b  d1,nic_rbcr0               ; set count.lo
  2865.  ror.w   #8,d1
  2866.  delay
  2867.  move.b  d1,nic_rbcr1               ; set count.hi
  2868.  delay
  2869.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
  2870.  ror.w   #8,d1
  2871.  
  2872. ; write the etherpacket header & prepare for the copy loop.
  2873.  lea     nic_data,a0
  2874.  sub.w   #ether_data+2,d1
  2875.  move.l  txbuffer(pc),(a0)
  2876.  move.w  d1,d0
  2877.  move.l  txbuffer+4(pc),(a0)
  2878.  and.w   #%0000000000111100,d1
  2879.  move.l  txbuffer+8(pc),(a0)
  2880.  lsr.w   #1,d1
  2881.  move.w  txbuffer+12(pc),(a0)
  2882.  lsr.w   #6,d0
  2883.  neg.w   d1
  2884.  move.w  (a1)+,(a0)
  2885.  jmp     .rw_startwrite(pc,d1.w)
  2886. .rw_dmawrite:
  2887.  move.l  (a1)+,(a0)
  2888.  move.l  (a1)+,(a0)
  2889.  move.l  (a1)+,(a0)
  2890.  move.l  (a1)+,(a0)
  2891.  move.l  (a1)+,(a0)
  2892.  move.l  (a1)+,(a0)
  2893.  move.l  (a1)+,(a0)
  2894.  move.l  (a1)+,(a0)
  2895.  move.l  (a1)+,(a0)
  2896.  move.l  (a1)+,(a0)
  2897.  move.l  (a1)+,(a0)
  2898.  move.l  (a1)+,(a0)
  2899.  move.l  (a1)+,(a0)
  2900.  move.l  (a1)+,(a0)
  2901.  move.l  (a1)+,(a0)
  2902.  move.l  (a1)+,(a0)
  2903. .rw_startwrite:
  2904.  subq.w  #1,d0
  2905.  bpl.s   .rw_dmawrite
  2906.  
  2907.  move.w  #30000,d0                  ; set timeout
  2908. .rw_check:
  2909.  delay
  2910.  move.b  nic_isr,d1                 ; wait for remote DMA complete
  2911.  and.b   #DSIS_RDC,d1
  2912.  dbne    d0,.rw_check
  2913.  
  2914. ; d0.w < 0   send timed out
  2915. ; d0.w >= 0  send succeeded
  2916.  
  2917.  delay
  2918.  move.b  #DSIS_RDC,nic_isr          ; Remote DMA complete
  2919.  swap    d1
  2920.  delay
  2921.  move.b  d1,nic_cr                  ; restore old command
  2922. ;rts
  2923.  
  2924.  else
  2925.  
  2926.  addq.w  #1,d1
  2927.  and.w   #-2,d1                     ; bump up count to even value
  2928.  swap    d1
  2929.  delay
  2930.  move.b  nic_cr,d1                  ; save old command
  2931.  swap    d1
  2932.  delay
  2933.  move.b  #DSIS_RDC,nic_isr          ; remote DMA complete
  2934.  delay
  2935.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  2936.  delay
  2937.  move.b  d0,nic_rsar0               ; set address.lo
  2938.  lsr.w   #8,d0
  2939.  delay
  2940.  move.b  d0,nic_rsar1               ; set address.hi
  2941.  delay
  2942.  move.b  d1,nic_rbcr0               ; set count.lo
  2943.  ror.w   #8,d1
  2944.  delay
  2945.  move.b  d1,nic_rbcr1               ; set count.hi
  2946.  delay
  2947.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
  2948.  
  2949. ; write the etherpacket header & prepare for the copy loop.
  2950.  lea     nic_data,a0
  2951.  ror.w   #8,d1
  2952.  move.w  txbuffer(pc),(a0)
  2953.  sub.w   #ether_data,d1
  2954.  move.w  txbuffer+2(pc),(a0)
  2955.  move.w  d1,d0
  2956.  move.w  txbuffer+4(pc),(a0)
  2957.  move.w  txbuffer+6(pc),(a0)
  2958.  and.w   #%0000000000011110,d1
  2959.  move.w  txbuffer+8(pc),(a0)
  2960.  lsr.w   #5,d0
  2961.  move.w  txbuffer+10(pc),(a0)
  2962.  neg.w   d1
  2963.  move.w  txbuffer+12(pc),(a0)
  2964.  jmp     .rw_startwrite(pc,d1.w)
  2965. .rw_dmawrite:
  2966.  move.w  (a1)+,(a0)
  2967.  move.w  (a1)+,(a0)
  2968.  move.w  (a1)+,(a0)
  2969.  move.w  (a1)+,(a0)
  2970.  move.w  (a1)+,(a0)
  2971.  move.w  (a1)+,(a0)
  2972.  move.w  (a1)+,(a0)
  2973.  move.w  (a1)+,(a0)
  2974.  move.w  (a1)+,(a0)
  2975.  move.w  (a1)+,(a0)
  2976.  move.w  (a1)+,(a0)
  2977.  move.w  (a1)+,(a0)
  2978.  move.w  (a1)+,(a0)
  2979.  move.w  (a1)+,(a0)
  2980.  move.w  (a1)+,(a0)
  2981.  move.w  (a1)+,(a0)
  2982. .rw_startwrite:
  2983.  subq.w  #1,d0
  2984.  bpl.s   .rw_dmawrite
  2985.  
  2986.  move.w  #30000,d0                  ; set timeout
  2987. .rw_check:
  2988.  delay
  2989.  move.b  nic_isr,d1                 ; wait for remote DMA complete
  2990.  and.b   #DSIS_RDC,d1
  2991.  dbne    d0,.rw_check
  2992.  
  2993. ; if d0.w<0 timed out
  2994. ; if d0.w>=0 succeeded
  2995.  
  2996.  delay
  2997.  move.b  #DSIS_RDC,nic_isr          ; Remote DMA complete
  2998.  swap    d1
  2999.  delay
  3000.  move.b  d1,nic_cr                  ; restore old command
  3001. ;rts
  3002.  
  3003.  endc
  3004.  ENDM
  3005.  
  3006.  
  3007.  
  3008. ;=========================================================
  3009. ;                      reset_nic()
  3010. ;=========================================================
  3011. ;
  3012. reset_nic:
  3013.  delay
  3014.  move.b  nic_rst,d0                       ; start reset pulse
  3015.  delay
  3016.  move.b  d0,nic_rst                       ; end reset pulse
  3017.  delay
  3018.  move.b  #DSCM_NODMA|DSCM_STOP,nic_cr     ; stop controller
  3019.  bsr.s   delay1500                        ; wait 1.5mS
  3020.  move.b  #$ff,nic_isr                     ; clear all nic ints
  3021.  rts
  3022.  
  3023.  
  3024. ;======================
  3025. ;  delay approx 1.5mS
  3026. ;======================
  3027. ;
  3028. delay1500:
  3029.  move.l   d0,-(sp)
  3030.  move.w   #1500,d0
  3031. .loop:
  3032.  tst.b    $bfe001       ; wait 1uS
  3033.  dbf      d0,.loop
  3034.  move.l   (sp)+,d0
  3035.  rts
  3036.  
  3037.  
  3038.  
  3039. ;========================================================================
  3040. ;                           init_nic(device)
  3041. ;                                      a1
  3042. ;========================================================================
  3043. ;
  3044. ; Set up the network card for online operation. We also get the hardware
  3045. ; station address from the nic's ROM.
  3046. ;
  3047. init_nic:
  3048.  movem.l d2/a5/a6,-(sp)
  3049.  move.l  exec_base(pc),a6
  3050.  move.l  a1,a5                             ; a5 = device data
  3051.  MYDISABLE                                 ; ignore ints while setting up
  3052.  btst    #DDB_NICUP,dd_flags(a5)
  3053.  bne     .ok                               ; already initialised ?
  3054.  
  3055.  move.b  #DSDC_WTS|DSDC_FT1|DSDC_BMS,dd_dcr(a5)  ; Word Xfer, FIFO, Burst
  3056.  move.b  #DSRC_AB|DSRC_AM,dd_rcr(a5)       ; accept broadcast & multicast
  3057.  btst    #DDB_PROM,dd_flags2(a5)
  3058.  beq.s   .notprom                              ; if promiscuous..
  3059.  or.b    #DSRC_SEP|DSRC_PRO|DSRC_AR,dd_rcr(a5) ; ..accept all packets
  3060. .notprom:
  3061.  
  3062.  move.b  #INTMASK,dd_imr(a5)               ; accept useful interrupts
  3063.  bsr     reset_nic                         ; reset the controller
  3064.  delay
  3065.  move.b  nic_cr,d0                         ; get command
  3066.  cmp.b   #DSCM_NODMA|DSCM_STOP,d0
  3067.  bne     .error1                           ; correct response ?
  3068.  
  3069.  delay
  3070.  move.b  dd_dcr(a5),nic_dcr                ; set data configuration register
  3071.  delay
  3072.  move.b  #0,nic_rbcr0                      ; clear remote byte count
  3073.  delay
  3074.  move.b  #0,nic_rbcr1                      ;         ''
  3075.  delay
  3076.  move.b  #DSRC_MON,nic_rcr                 ; set rx to monitor mode
  3077.  delay
  3078.  move.b  #DSTC_LB0,nic_tcr                 ; set tx to loopback mode 1
  3079.  delay
  3080.  move.b  #(RBUFEND/256)-1,nic_bnry         ; set boundary page
  3081.  delay
  3082.  move.b  #RBUF/256,nic_pstart              ; set start of rx ring buffer
  3083.  delay
  3084.  move.b  #RBUFEND/256,nic_pstop            ; set end of rx ring buffer
  3085.  delay
  3086.  move.b  #$ff,nic_isr                      ; clear all interrupts
  3087.  delay
  3088.  move.b  #0,nic_imr                        ; no interrupts allowed
  3089.  delay
  3090.  move.b  nic_rsr,d0
  3091.  delay
  3092.  move.b  nic_ncr,d0
  3093.  delay
  3094.  move.b  nic_cntr0,d0                      ; read status registers
  3095.  delay
  3096.  move.b  nic_cntr1,d0
  3097.  delay
  3098.  move.b  nic_cntr2,d0
  3099.  delay
  3100.  move.b  #ETHER_ADDR_SIZE*2,nic_rbcr0      ; byte count low = (words)
  3101.  delay
  3102.  move.b  #0,nic_rbcr1                      ; byte count high = 0
  3103.  delay
  3104.  move.b  #0,nic_rsar0                      ; remote start addr low = 0 (ROM)
  3105.  delay
  3106.  move.b  #0,nic_rsar1                      ; remote start addr high = 0 (ROM)
  3107.  delay
  3108.  move.b  #DSCM_RREAD,nic_cr                ; start remote read to get
  3109.  delay                                     ; station address from ROM
  3110.  lea     dd_romstationaddress(a5),a0
  3111.  
  3112.  moveq   #ETHER_ADDR_SIZE,d0
  3113. .getaddr:
  3114.  move.b  nic_data,(a0)+                    ; get ROM station address
  3115.  subq.l  #1,d0                             ; NOTE: 'move.b' as ROM is 8 bit
  3116.  bne.s   .getaddr                          
  3117.  
  3118.  move.w  #30000,d1
  3119. .waitloop:
  3120.  delay
  3121.  move.b  nic_isr,d0
  3122.  and.b   #DSIS_RDC,d0                      ; wait for remote DMA complete
  3123.  dbne    d1,.waitloop
  3124.  
  3125.  tst.w   d1
  3126.  bmi     .error2                           ; error if timed out
  3127.  delay
  3128.  move.b  #DSIS_RDC,nic_isr                 ; clear remote DMA complete int
  3129.  
  3130.  lea     dd_romstationaddress(a5),a0
  3131.  tst.b   (a0)
  3132.  bmi.s   .badaddr                          ; good station address ?
  3133.  
  3134.  move.l  2(a0),d0
  3135.  beq.s   .badaddr
  3136.  cmp.l   #-1,d0
  3137.  bne.s   .gotstation
  3138. .badaddr:
  3139.  bug     <"cnet: bad station address %08lx%04lx, using default",10>,(a0),2(a0)
  3140.  lea     default_address(pc),a0
  3141. .gotstation:
  3142.  bug     <"cnet: station address set to %08lx%04lx",10>,(a0),2(a0)
  3143.  
  3144.  lea     dd_stationaddress(a5),a1
  3145.  move.l  (a0)+,(a1)+                       ; copy address to device data
  3146.  move.w  (a0)+,(a1)+
  3147.  
  3148.  lea     dd_stationaddress(a5),a0
  3149.  delay
  3150.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_STOP,nic_cr ; select bank 1
  3151.  delay
  3152.  move.b  (a0)+,nic_par0
  3153.  delay
  3154.  move.b  (a0)+,nic_par1
  3155.  delay
  3156.  move.b  (a0)+,nic_par2
  3157.  delay                                     ; set station address
  3158.  move.b  (a0)+,nic_par3
  3159.  delay
  3160.  move.b  (a0)+,nic_par4
  3161.  delay
  3162.  move.b  (a0),nic_par5
  3163.  delay
  3164.  move.b  #RBUF/256,nic_curr                ; set current page for rx
  3165.  move.b  #DSCM_NODMA|DSCM_START,d0
  3166.  delay
  3167.  move.b  d0,nic_cr                         ; start controller
  3168.  delay
  3169.  cmp.b   nic_cr,d0
  3170.  bne     .error3                           ; command accepted ?
  3171.  
  3172.  bsr     put_multi                         ; load multicast registers
  3173.  
  3174.  delay
  3175.  move.b  dd_rcr(a5),nic_rcr                ; normal rx mode
  3176.  delay
  3177.  move.b  #0,nic_tcr                        ; loopback mode off
  3178.  delay
  3179.  move.b  #TBUF/256,nic_tpsr                ; init tx start page
  3180.  delay
  3181.  move.b  #$ff,nic_isr                      ; clear all interrupts
  3182.  delay
  3183.  move.b  dd_imr(a5),nic_imr                ; enable nic interrupts
  3184.  
  3185.  bset    #DDB_NICUP,dd_flags(a5)           ; nic is initialised
  3186.  
  3187. .ok:
  3188.  lea     dd_devicestats+s2ds_laststart(a5),a0
  3189.  bsr     get_time                          ; record start time_of_day
  3190.  bug     <"cnet: init_nic OK",10>
  3191.  moveq   #0,d0                             ; return OK
  3192.  
  3193. .done:
  3194.  MYENABLE                                  ; allow interrupt processing
  3195.  movem.l (sp)+,d2/a5/a6
  3196.  rts
  3197.  
  3198.  
  3199. .error1:
  3200.  bug     <"cnet: failed reset, card not compatible?",10>
  3201.  bra.s   .bad
  3202.  
  3203. .error2:
  3204.  bug     <"cnet: DMA timeout getting station address!",10>
  3205.  bra     .reset
  3206.  
  3207. .error3:
  3208.  bug     <"cnet: failed to start controller, card faulty?",10>
  3209.  
  3210. .reset:
  3211.  bsr     reset_nic                         ; reset nic after malfunction
  3212. .bad:
  3213.  
  3214.  moveq   #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
  3215.  bsr     DoEvent
  3216.  moveq   #-1,d0                            ; return error
  3217.  bra     .done
  3218.  
  3219.  
  3220.  
  3221. ;--------------------------------------------------------
  3222. ;                     kill_nic(device)
  3223. ;                                a1
  3224. ;--------------------------------------------------------
  3225. ;
  3226. kill_nic:
  3227.  bug     <"cnet: kill_nic",10>
  3228.  
  3229.  move.l  a6,-(sp)
  3230.  move.l  exec_base(pc),a6
  3231.  MYDISABLE
  3232.  
  3233.  bclr    #DDB_NICUP,dd_flags(a1)
  3234.  beq.s   .done                    ; already killed ?
  3235.  bsr     reset_nic                ; reset controller
  3236.  delay
  3237.  move.b  #DSRC_MON,nic_rcr        ; set rx to monitor mode
  3238.  delay
  3239.  move.b  #DSTC_LB0,nic_tcr        ; set tx to loopback mode
  3240. .done:
  3241.  
  3242.  MYENABLE
  3243.  move.l  (sp)+,a6
  3244.  rts
  3245.  
  3246.  
  3247.  
  3248. ;========================================================
  3249. ;                 txintcode(device)
  3250. ;                             a1
  3251. ;========================================================
  3252. ;
  3253. ;  send packets to network card. packets will be put
  3254. ;  into the card's onboard 16 bit ram, and then
  3255. ;  transmitted to the wire.
  3256. ;
  3257. ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
  3258. ;
  3259. txintcode:
  3260.  movem.l d2-d4/a2-a3/a6,-(sp)
  3261.  move.l  exec_base(pc),a6
  3262.  move.l  a1,a5                      ; a5 = device
  3263.  
  3264. .next:
  3265.  btst    #DDB_TX,dd_flags(a5)       ; quit if tx in progress (status int
  3266.  bne.s   .done                      ; will restart us when tx complete)
  3267.  
  3268.  lea     dd_writelist(a5),a0
  3269.  MYREMHEAD                          ; remove top ioreq
  3270.  bne.s   .gotreq                    ; any ioreqs to process?
  3271.  
  3272. .done:
  3273.  movem.l (sp)+,d2-d4/a2-a3/a6
  3274.  moveq   #0,d0
  3275.  rts
  3276.  
  3277.  
  3278. .gotreq:
  3279.  move.l  d0,a3                      ; a3 = ioreq
  3280.  
  3281.  lea     txbuffer(pc),a1            ; a1 = our internal packet buffer
  3282.  move.l  ios2_buffermanagement(a3),a2
  3283.  move.l  ios2_datalength(a3),d4     ; default: raw packet's full length
  3284.  move.l  ios2_packettype(a3),d3     ; d3 = packettype (must be in d3 in non-raw too!!!)
  3285.  tst.b   io_flags(a3)               ; (test SANA2IOB_RAW) raw packets?
  3286.  bmi.s   .send
  3287.  
  3288. ; ok. it's not raw packet so we need to build etherheader for it.
  3289. ; first destination and source addresses then packet type. easy!
  3290.  
  3291.  lea     ios2_dstaddr(a3),a0        ; dstaddress
  3292.  move.l  (a0)+,(a1)+
  3293.  move.w  (a0)+,(a1)+
  3294.  lea     dd_stationaddress(a5),a0   ; from address
  3295.  move.l  (a0)+,(a1)+
  3296.  move.w  (a0)+,(a1)+
  3297.  move.w  d3,(a1)+                   ; insert packettype into packet
  3298.  add.w   #ether_data,d4             ; d4 = length of header + data
  3299.  
  3300.  
  3301. .send:
  3302. ; Do we have the tag for DMA?
  3303.  lea     bufman_dmacopyfrombuf32(a2),a2
  3304.  move.l  a1,d2                      ; d2 = where to copyfrom
  3305.  move.l  (a2)+,d0
  3306.  beq.s   .nodma
  3307.  
  3308. ; Ask for the DMA address
  3309.  move.l  d0,a1
  3310.  move.l  ios2_data(a3),a0           ; a0=abstract magic cookie ios2_Data
  3311.  jsr     (a1)
  3312.  tst.l   d0                         ; dma possible?
  3313.  move.l  d0,a1
  3314. ; If dma is possible we now have the direct application buffer
  3315. ; in a1.. and we can use that directly with RemoteWrite! cool.
  3316.  ifd     verbose
  3317.  tst.l   d0
  3318.  beq.s   .v1_nodma
  3319.  bug     <"cnet: using DMA write from $%08lx!",10>,a1
  3320.  tst.l   d0
  3321. .v1_nodma:
  3322.  endc
  3323.  bne.s   .copyok                    ; do it with DMA?
  3324.  
  3325.  
  3326. .nodma:
  3327. ; Ohwell, the caller doesn't support DMA transfer, so lets fall
  3328. ; back to regular copyfrom.
  3329.  
  3330.  move.l  d2,a0                      ; a0=to (contiguous)
  3331.  move.l  ios2_data(a3),a1           ; a1=from (abstract)
  3332.  move.l  (a2),a2                    ; get bufman_copyfrombuf
  3333.  move.l  ios2_datalength(a3),d0     ; d0=n
  3334.  jsr     (a2)
  3335.  tst.l   d0
  3336.  beq     .copyfromfail              ; oh fuck.. copyfrombuf failed!
  3337.  
  3338. ; we can return the ioreq now!
  3339.  move.l  a3,a1
  3340.  sub.l   a3,a3
  3341.  bsr     TermIO                     ; finish IOrequest
  3342.  
  3343.  lea     txbuffer+ether_data(pc),a1 ; non-DMA so use txbuffer for copy!!
  3344. .copyok:
  3345.  
  3346.  moveq   #ETHER_MIN_LEN,d0
  3347.  cmp.l   d0,d4
  3348.  bge.s   .min                       ; d4 adjusted to legal packet size
  3349.  move.l  d0,d4
  3350. .min:
  3351.  
  3352.  ifd     verbose
  3353.  move.l  a1,-(sp)
  3354.  moveq   #0,d1
  3355.  move.w  txbuffer+ether_type(pc),d1
  3356.  bug     <"cnet: wrpkt %08lx%04lx >> %08lx%04lx ">,txbuffer+6(pc),txbuffer+8(pc),txbuffer(pc),txbuffer+2(pc)
  3357.  cmp.w   #1500,d1
  3358.  bhs.s   .type
  3359.  bug     <"(IEEE802.3)len %ld, ">,d1
  3360.  bra.s   .bytes
  3361. .type:
  3362.  bug     <"type %ld, ">,d1
  3363. .bytes:
  3364.  bug     <"%ld bytes",10>,d4
  3365.  moveq   #-ether_data,d0            ; show only the data
  3366.  add.l   d4,d0
  3367.  bsr     showpkt
  3368.  move.l  (sp)+,a1
  3369.  endc
  3370.  
  3371.  
  3372. ; copy the transfer buffer to cards memory
  3373.  
  3374.  move.w  #TBUF,d0
  3375.  move.w  d4,d1
  3376. ; a1 = txbuffer (or DMA buffer)
  3377. ;bsr     RemoteWrite                ; put packet into nic tx buffer
  3378.  REMOTEWRITE
  3379.  tst.w   d0
  3380.  bmi.s   .xmiterr
  3381.  
  3382.  
  3383.  
  3384. ; now really start the transfer:
  3385.  
  3386.  MYDISABLE                          ; disable interrupts during tx setup
  3387.  bset    #DDB_TX,dd_flags(a5)       ; set our "buffer full" flag
  3388.  delay
  3389.  move.b  d4,nic_tbcr0               ; set tx byte count lo
  3390.  ror.w   #8,d4
  3391.  delay
  3392.  move.b  d4,nic_tbcr1               ; set tx byte count hi
  3393.  ror.w   #8,d4
  3394.  delay
  3395.  move.b  #DSCM_NODMA|DSCM_TRANS|DSCM_START,nic_cr ; start tx
  3396.  MYENABLE                           ; enable interrupts
  3397.  
  3398. ; update statistics:
  3399.  
  3400.  move.l  dd_tracklist(a5),a0
  3401. .getstats:
  3402.  move.l  (a0),d2                    ; tracking packettypes ?
  3403.  beq.s   .statsdone
  3404.  cmp.l   ss2_ptype(a0),d3           ; stats entry for our type ?
  3405.  beq.s   .gotstats
  3406.  move.l  d2,a0                      ; try next stats entry
  3407.  bra.s   .getstats
  3408.  
  3409. .gotstats:
  3410.  add.l   d4,ss2_stats+s2pts_txbytes(a0)
  3411.  addq.l  #1,ss2_stats+s2pts_txpackets(a0)
  3412. .statsdone:
  3413.  
  3414.  
  3415. .termio:
  3416.  move.l  a3,d0                      ; have we replied it already?
  3417.  beq     .next                      ; we have! process next ioreq
  3418.  
  3419.  move.l  a3,a1
  3420.  bsr     TermIO                     ; finish IOrequest
  3421.  bra     .next                      ; process next ioreq
  3422.  
  3423.  
  3424. .copyfromfail:
  3425. ; note: doesn't get called if a3=0
  3426.  moveq   #S2EVENT_TX|S2EVENT_BUFF,d0
  3427.  bsr     DoEvent
  3428.  clr.l   ios2_datalength(a3)
  3429.  moveq   #S2WERR_BUFF_ERROR,d0
  3430.  move.b  #S2ERR_NO_RESOURCES,io_error(a3)
  3431.  move.l  d0,ios2_wireerror(a3)
  3432.  bra.s   .termio
  3433.  
  3434. .xmiterr:
  3435.  moveq   #S2EVENT_ERROR|S2EVENT_TX,d0
  3436.  bsr     DoEvent
  3437.  bra.s   .termio
  3438.  
  3439.  
  3440.  
  3441. ;============================================================
  3442. ;                   rxintcode(device)
  3443. ;                               a1
  3444. ;============================================================
  3445. ;
  3446. ;                service rx interrupts
  3447. ;
  3448. ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
  3449. ;
  3450. rxintcode:
  3451.  movem.l d6/d7/a6,-(sp)
  3452.  move.l  exec_base(pc),a6
  3453.  move.l  a1,a5                             ; a5 = device
  3454.  
  3455. .nextpage:
  3456.  
  3457.  MYDISABLE
  3458.  delay
  3459.  moveq   #0,d7
  3460.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_START,nic_cr ; select bank 1
  3461.  move.b  nic_curr,d7                       ; d7 = current page
  3462.  delay
  3463.  move.b  #DSCM_NODMA|DSCM_START,nic_cr     ; select bank 0
  3464.  MYENABLE
  3465.  
  3466.  moveq   #0,d6
  3467.  delay
  3468.  move.b  nic_bnry,d6
  3469.  addq.w  #1,d6                             ; d6 = next page (boundary+1)
  3470.  cmp.w   #RBUFEND/256,d6
  3471.  blo.s   .nowrap                           ; end of buffer mem  ?
  3472.  moveq   #RBUF/256,d6                      ; wrap around to start
  3473. .nowrap:
  3474.  cmp.w   d6,d7                             ; current page = next page ?
  3475.  beq     .done                             ; if so then nothing to get
  3476.  
  3477.  ifgt    0
  3478.  move.w  d6,d0
  3479.  lea     rx_header(pc),a1                  ; a1 = buffer
  3480.  lsl.w   #8,d0                             ; d0 = 16 bit page address
  3481.  moveq   #prhdr_sizeof+ether_data,d1
  3482.  bsr     RemoteRead                        ; get packet header
  3483.  
  3484.  else
  3485.  
  3486. ; inlined RemoteRead:
  3487.  
  3488.  lea     nic_data,a0
  3489.  lea     rx_header(pc),a1                  ; a1 = buffer
  3490.  delay
  3491.  move.b  nic_cr,d1               ; save old command
  3492.  delay
  3493.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  3494.  delay
  3495.  move.b  #prhdr_sizeof+ether_data,nic_rbcr0 ;   set count.lo
  3496.  delay
  3497.  move.b  #0,nic_rbcr1            ;   set count.hi
  3498.  delay
  3499.  move.b  #0,nic_rsar0            ;   set address.lo
  3500.  delay
  3501.  move.b  d6,nic_rsar1            ;   set address.hi  (d6=16 bit page address hi)
  3502.  delay
  3503.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  3504.  
  3505.  ; transfer prhdr_sizeof+ether_data = 4+14 = 18 = 2*9
  3506.  
  3507.  ifd     turboio
  3508.  move.l  (a0),(a1)+              ; 4*4 = 16
  3509.  move.l  (a0),(a1)+
  3510.  move.l  (a0),(a1)+
  3511.  move.l  (a0),(a1)+
  3512.  else
  3513.  move.w  (a0),(a1)+              ; 4*4 = 16
  3514.  move.w  (a0),(a1)+
  3515.  move.w  (a0),(a1)+
  3516.  move.w  (a0),(a1)+
  3517.  move.w  (a0),(a1)+
  3518.  move.w  (a0),(a1)+
  3519.  move.w  (a0),(a1)+
  3520.  move.w  (a0),(a1)+
  3521.  endc
  3522.  move.w  (a0),(a1)+              ; +2
  3523.  
  3524.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete
  3525.  delay
  3526.  move.b  d1,nic_cr               ; restore old command
  3527.  
  3528.  endc
  3529.  
  3530.  move.b  rx_header+prhdr_status(pc),d0
  3531.  and.b   #DSRS_RPC,d0                      ; complete packet received ?
  3532.  bne.s   .goodpacket
  3533.  
  3534.  bug     <"cnet: incomplete packet received",10>
  3535.  addq.l  #1,dd_devicestats+s2ds_baddata(a5) ; count bad packets received
  3536.  bra.s   .next
  3537.  
  3538. .goodpacket:
  3539.  addq.l  #1,dd_devicestats+s2ds_packetsreceived(a5) ; count packets received
  3540.  
  3541.  move.l  a5,a0
  3542.  move.w  d6,d0
  3543. ;lea     rx_header(pc),a1
  3544.  bsr.s   readpacket                        ; feed packet into waiting ioreqs
  3545.  
  3546. .next:
  3547.  moveq   #0,d0
  3548.  move.b  rx_header+prhdr_nxtpg(pc),d0      ; get next page number
  3549.  move.w  d0,d7
  3550.  subq.w  #1,d0                             ; nxtpage-1 = new boundary
  3551.  cmp.w   #RBUF/256,d0
  3552.  bge.s   .boundary                         ; wrap if before 1st page
  3553.  moveq   #(RBUFEND/256)-1,d0
  3554. .boundary:
  3555.  delay
  3556.  move.b  d0,nic_bnry                       ; set new boundary
  3557.  bra     .nextpage                         ; back for more
  3558.  
  3559. .done:
  3560.  delay
  3561.  move.b  #DSCM_NODMA|DSCM_START,nic_cr     ; select bank 0
  3562.  MYDISABLE
  3563.  delay
  3564.  move.b  nic_rsr,d0                        ; read rx status
  3565.  delay
  3566.  move.b  nic_cntr0,d0
  3567.  delay
  3568.  move.b  nic_cntr1,d0                      ; read counters
  3569.  delay
  3570.  move.b  nic_cntr2,d0
  3571.  or.b    #DSIM_OVWE|DSIM_RXEE|DSIM_PRXE,dd_imr(a5)
  3572.  move.b  dd_imr(a5),nic_imr                ; allow rx interrupts
  3573.  MYENABLE
  3574.  
  3575.  movem.l (sp)+,d6/d7/a6
  3576.  moveq   #0,d0
  3577.  rts
  3578.  
  3579.  
  3580.  
  3581. ;==============================================================
  3582. ;             readpacket( device, [pkthdr], page )
  3583. ;                           a0     [a1]     d0.w
  3584. ;==============================================================
  3585. ;
  3586. ; get packet from network card and feed it to all different
  3587. ; CMD_READ queues. Also call packet filter before doing the copy.
  3588. ; Note that this is a major improvement to previous implementation,
  3589. ; that only kept one single list of CMD_READs. This finally fixes
  3590. ; sanamon for example.
  3591. ;
  3592. ; Inputs:
  3593. ;
  3594. ;       pkthdr = packet header info extracted from nic
  3595. ;
  3596. ;       page = 256 byte page in nic RAM that holds packet
  3597. ;
  3598. ;
  3599. readpacket:
  3600.  movem.l d2-d7/a2-a6,-(sp)
  3601.  
  3602.  moveq   #0,d6
  3603.  move.w  d0,d7                          ; d7 = page
  3604.  move.l  a0,a5                          ; a5 = device
  3605.  move.b  rx_header+prhdr_sz1(pc),d6
  3606.  moveq   #0,d3
  3607.  lsl.w   #8,d6
  3608.  move.w  rx_header+prhdr_sizeof+ether_type(pc),d3
  3609.  move.b  rx_header+prhdr_sz0(pc),d6
  3610.  lsl.w   #8,d7                          ; address=page*256
  3611.  sub.w   #prhdr_sizeof+ether_data,d6    ; d6 = length of read
  3612.  add.w   #prhdr_sizeof+ether_data,d7    ; skip pageheader and etherheader
  3613.  
  3614. ; dropflag is set to true if at least one protocol stack managed
  3615. ; to get the packet. If this still is zero after the following loop
  3616. ; then I try to feed to for pending S2_READORPHAN request, if any.
  3617.  
  3618.  moveq   #0,d4                          ; dropflag
  3619.  
  3620.  move.l  dd_bufmanlist(a5),a3           ; a3 = first bufman
  3621.  bra.s   .start
  3622.  
  3623. ; scan each CMD_READ callers bufmanlist until we find the ioreq
  3624. ; that want this type of packet or till end of list.
  3625.  
  3626. .nextreq:
  3627.  move.l  (a3),d0
  3628.  beq.s   .nextbufman                    ; end of this CMD_READ list ?
  3629.  cmp.l   ios2_packettype(a3),d3
  3630.  beq.s   .iwantyou                      ; does it want our packet ?
  3631.  cmp.w   #1500,d3
  3632.  bhi.s   .nextnode                      ; accept 802.3 packets
  3633.  cmp.l   #1500,ios2_packettype(a3)
  3634.  bls.s   .iwantyou
  3635. .nextnode:
  3636.  move.l  d0,a3
  3637.  bra.s   .nextreq
  3638.  
  3639. .iwantyou:
  3640. ; a3 = ioreq
  3641.  moveq   #1,d2                          ; use packetfilter
  3642.  bsr     .gotreq
  3643. ; note that we only offer it once per caller!
  3644.  
  3645. .nextbufman:
  3646.  move.l  d5,a3                          ; a3 = next bufman node in list
  3647. .start:
  3648.  move.l  (a3),d5
  3649.  move.l  bufman_rxqueue(a3),a3          ; get pending CMD_READ's list
  3650.  bne.s   .nextreq                       ; end of bufman list ?
  3651.  
  3652. ; Now we've tried to give the packet to every CMD_READ caller,
  3653. ; and d4 contains the number of iorequests that were succesfully
  3654. ; returned. If d4 is 0 at this point no-one wanted this packet.
  3655.  
  3656.  tst.l   d4                             
  3657.  beq.s   .gotdropped                    ; did oneone want it?
  3658.  
  3659. ; Okay, at least one CMD_READ caller got the packet, so we're happy
  3660. ; now and can quit.
  3661.  
  3662. .done:
  3663.  movem.l (sp)+,d2-d7/a2-a6
  3664.  rts
  3665.  
  3666.  
  3667. .gotdropped:
  3668.  
  3669. ; so there were no outstanding CMD_READs or the packet wasn't
  3670. ; accepted by any of them. Okay, check if we have any pending
  3671. ; S2_READORPHAN ioreq in list and if we have return this packet
  3672. ; with it. Note that packet filter must not be used for this
  3673. ; time!
  3674.  
  3675.  addq.l  #1,dd_devicestats+s2ds_unknowntypesreceived(a5)
  3676.  move.l  dd_orphanlist(a5),a3           ; get first S2_READORPHAN available
  3677.  tst.l   (a3)
  3678.  beq.s   .dotrack                       ; got an orphan ioreq ?
  3679.  
  3680. ; d4 = whatever, not important here
  3681. ; a3 = ioreq
  3682.  moveq   #0,d2                          ; indicate S2_READORPHAN call
  3683.  bsr.s   .gotreq
  3684.  
  3685. .dotrack:
  3686.  
  3687. ; Update dropped packet statistics, if requested.
  3688.  
  3689.  move.l  dd_tracklist(a5),a0
  3690. .getstat:
  3691.  move.l  (a0),d0                        ; tracking packettypes ?
  3692.  beq.s   .donetrk
  3693.  cmp.l   ss2_ptype(a0),d3               ; get tracking entry for this type
  3694.  beq.s   .dropped
  3695.  move.l  d0,a0                          ; next tracking entry
  3696.  bra.s   .getstat
  3697.  
  3698. .dropped:
  3699.  addq.l  #1,ss2_stats+s2pts_packetsdropped(a0) ; another packet dropped
  3700. .donetrk:
  3701.  
  3702.  bug     <"cnet: packet type %ld dropped",10>,d3
  3703.  
  3704.  moveq   #S2EVENT_ERROR|S2EVENT_RX,d0
  3705.  bsr     DoEvent
  3706.  bra     .done
  3707.  
  3708.  
  3709.  
  3710. .gotreq:
  3711.  
  3712. ; Here we have a ioreq in a3 that has requested packets of this type.
  3713. ; 1st we extract the packet from the card unless we have already done
  3714. ; so. d2 = 0 if this ioreq is S2_READORPHAN call (packetfilter must
  3715. ; not be used). if d2 = 1 then this is a regular CMD_READ and
  3716. ; packetfilter must be called.
  3717.  
  3718.  tst.w   d7
  3719.  beq.s   .gotalready                    ; have we already read it ?
  3720.  
  3721.  lea     rxbuffer+ether_data(pc),a1
  3722.  move.w  d7,d0                          ; (we only get the user stuff here)
  3723.  move.w  d6,d1
  3724. ;bsr     RemoteRead                     ; get packet user data from nic
  3725.  REMOTEREAD
  3726.  
  3727.  ifd     verbose
  3728.  bug     <"cnet: rdpkt %08lx%04lx < %08lx%04lx, ">,rxbuffer+ether_dest(pc),rxbuffer+ether_dest+2(pc),rxbuffer+ether_src(pc),rxbuffer+ether_src+2(pc)
  3729.  cmp.w   #1500,d3
  3730.  bhi.s   .type
  3731.  bug     <"(IEEE802.3)len %ld, ">,d3
  3732.  bra.s   .bytes
  3733. .type:
  3734.  bug     <"type %ld, ">,d3
  3735. .bytes:
  3736.  moveq   #ether_data,d0
  3737.  add.l   d6,d0
  3738.  bug     <"%ld bytes",10>,d0
  3739.  lea     rxbuffer+ether_data(pc),a1
  3740.  move.l  d6,d0
  3741.  bsr     showpkt
  3742.  endc
  3743.  
  3744.  
  3745. ; Update the packet statistics if required.
  3746.  
  3747.  move.l  dd_tracklist(a5),a0
  3748. .getstats:
  3749.  move.l  (a0),d0                        ; tracking packettypes ?
  3750.  beq.s   .received
  3751.  cmp.l   ss2_ptype(a0),d3               ; find stats entry for our type
  3752.  beq.s   .gotstats
  3753.  move.l  d0,a0
  3754.  bra.s   .getstats
  3755. .gotstats:
  3756.  add.l   d6,ss2_stats+s2pts_rxbytes(a0) ; update stats
  3757.  addq.l  #1,ss2_stats+s2pts_rxpackets(a0)
  3758. .received:
  3759.  
  3760.  moveq   #0,d7                          ; don't try to read it from hw anymore
  3761. .gotalready
  3762.  
  3763.  
  3764.  
  3765. ; next figure out if this ioreq asked the raw or non-raw data,
  3766. ; and skip ether_data bytes from the buffer start if it asked
  3767. ; raw.
  3768.  
  3769.  move.l  d6,ios2_datalength(a3)         ; user data size
  3770.  lea     rxbuffer+ether_data(pc),a6     ; a6=user data
  3771.  tst.b   io_flags(a3)                   ; (test SANA2IOB_RAW)
  3772.  bpl.s   .notraw                        ; is etherheader wanted ?
  3773.  add.w   #ether_data+4,ios2_datalength+2(a3) ; raw data size
  3774.  lea     rxbuffer(pc),a6                ; a6=raw data
  3775. .notraw:
  3776.  
  3777. ; now build up the ios2 structure enough so we can call the packet
  3778. ; filter.
  3779.  
  3780.  lea     ios2_dstaddr(a3),a0
  3781.  lea     rxbuffer+ether_dest(pc),a1     ; or: rx_header+prhdr_sizeof+ether_dest
  3782.  move.l  (a1)+,(a0)+                    ; extract the dst address
  3783.  move.w  (a1)+,(a0)+
  3784.  lea     ios2_packettype(a3),a0
  3785.  move.l  d3,(a0)+                       ; packet type
  3786.  move.l  (a1)+,(a0)+                    ; extract the src address
  3787.  move.w  (a1)+,(a0)+
  3788.  
  3789. ; call the packet filter, if available. real men don't use filters. :-)
  3790. ; the truth is out there
  3791.  
  3792.  tst.l   d2
  3793.  move.l  ios2_buffermanagement(a3),a0
  3794.  beq.s   .marlboro                      ; S2_READORPHAN must not use filter!
  3795.  move.l  bufman_packetfilter(a0),d0
  3796.  beq.s   .marlboro                      ; did the caller provide packet filter ?
  3797.  move.l  d0,a0                          ; a0=hook
  3798.  move.l  a6,a1                          ; a1=data
  3799.  move.l  8(a0),a4                       ; h_entry - get hook assembler entry point
  3800.  move.l  a3,a2                          ; a2=ios2
  3801.  jsr     (a4)
  3802.  tst.l   d0
  3803.  beq     .ignore
  3804. .marlboro: ;-!
  3805.  
  3806. ; ok. the packet didn't get filtered, set the BCAST and MCAST
  3807. ; flags according to dstaddr.
  3808.  
  3809.  btst    #0,ios2_dstaddr(a3)            ; address = Multicast ?
  3810.  beq.s   .nmcast
  3811.  cmp.l   #$ffffffff,ios2_dstaddr(a3)
  3812.  bne.s   .nbcast                        ; address = Broadcast ?
  3813.  cmp.w   #$ffff,ios2_dstaddr+4(a3)
  3814.  bne.s   .nbcast
  3815.  bset    #SANA2IOB_BCAST,io_flags(a3)   ; set BROADCAST flag in ioreq
  3816.  bra.s   .nmcast
  3817. .nbcast:
  3818.  bset    #SANA2IOB_MCAST,io_flags(a3)   ; set MULTICAST flag in ioreq
  3819. .nmcast:
  3820.  
  3821. ; finally copy the packet data!
  3822.  
  3823.  move.l  ios2_data(a3),a0
  3824.  move.l  ios2_buffermanagement(a3),a2
  3825.  move.l  a6,a1
  3826.  move.l  bufman_copytobuf(a2),a2
  3827.  move.l  ios2_datalength(a3),d0
  3828.  jsr     (a2)                           ; call copytobuf
  3829.  tst.l   d0
  3830.  beq.s   .copytobuferr
  3831.  
  3832.  addq.l  #1,d4                          ; mark that it wasn't dropped!
  3833.  
  3834.  ifd     verbose
  3835.  bug     <"cnet: copytobuffed packet ior %08lx %08lx%04lx < %08lx%04lx, type %ld, %ld bytes, ">,a3,ios2_dstaddr(a3),ios2_dstaddr+2(a3),ios2_srcaddr(a3),ios2_srcaddr+2(a3),ios2_packettype(a3),ios2_datalength(a3)
  3836.  tst.b   io_flags(a3)
  3837.  bpl.s   .v1
  3838.  bug     <"RAW ">
  3839. .v1:
  3840.  btst    #SANA2IOB_BCAST,io_flags(a3)
  3841.  beq.s   .v2
  3842.  bug     <"BCAST ">
  3843. .v2:
  3844.  btst    #SANA2IOB_MCAST,io_flags(a3)
  3845.  beq.s   .v3
  3846.  bug     <"MCAST ">
  3847. .v3:
  3848.  bug     <10>
  3849.  endc
  3850.  
  3851. .termit:
  3852.  move.l  a3,a1
  3853.  REMOVE                                 ; pull it off the list
  3854.  move.l  a3,a1
  3855.  bra     TermIO                         ; IO finished
  3856.  
  3857.  
  3858. .ignore:
  3859.  bug     <"cnet: packet type %ld for %08lx ior filtered",10>,d3,a3
  3860.  
  3861. ; the packet got rejected by packet filter!
  3862.  rts
  3863.  
  3864.  
  3865. .copytobuferr:
  3866. ; oh fuck.. copytobuf failed!
  3867.  bug     <10,"cnet: copytobuf failed!",10>
  3868.  
  3869.  moveq   #S2EVENT_RX|S2EVENT_BUFF,d0
  3870.  bsr     DoEvent
  3871.  clr.l   ios2_datalength(a3)
  3872.  moveq   #S2WERR_BUFF_ERROR,d0
  3873.  move.b  #S2ERR_NO_RESOURCES,io_error(a3)
  3874.  move.l  d0,ios2_wireerror(a3)
  3875.  bra.s   .termit
  3876.  
  3877.  
  3878.  
  3879.  
  3880. ;======================================================================
  3881. ;                  init_card(device)
  3882. ;                              a1
  3883. ;======================================================================
  3884. ;
  3885. ;                    Initialise PCMCIA card
  3886. ;
  3887. init_card:
  3888.  bug     <"cnet: init_card",10>
  3889.  
  3890.  movem.l d3-d6/a3/a6,-(sp)
  3891.  move.l  a1,a3                        ; a3 = device
  3892.  btst    #DDB_OWNED,dd_flags(a3)      ; do we own the card already?
  3893.  bne     .owned
  3894.  
  3895.  move.l  dd_cardres(a3),d0
  3896.  bne.s   .gotres
  3897.  move.l  exec_base(pc),a6
  3898.  lea     cardname(pc),a1
  3899.  jsr     _LVOOpenResource(a6)         ; open credit card resource
  3900.  move.l  d0,dd_cardres(a3)
  3901.  beq     .error
  3902. .gotres:
  3903.  
  3904.  lea     dd_cardhandle(a3),a1
  3905.  
  3906.  lea     dd_cardremoved(a3),a0        ; init interrupt for card removed
  3907.  move.l  a3,is_data(a0)
  3908.  move.l  #card_removed_code,is_code(a0)
  3909.  move.l  a0,cah_CardRemoved(a1)
  3910.  
  3911.  lea     dd_cardinserted(a3),a0       ; init interrupt for card inserted
  3912.  move.l  a3,is_data(a0)
  3913.  move.l  #card_inserted_code,is_code(a0)
  3914.  move.l  a0,cah_CardInserted(a1)
  3915.  
  3916.  lea     dd_cardstatus(a3),a0         ; init interrupt for status change
  3917.  move.l  a3,is_data(a0)
  3918.  
  3919.  move.l  dd_cardres(a3),a6
  3920.  cmp.w   #39,LIB_VERSION(a6)          ; got CARDB_POSTSTATUS (v39+) ?
  3921.  blo.s   .oldie
  3922.  
  3923.  move.l  #status_int_code_v39,is_code(a0)
  3924.  move.b  #CARDF_IFAVAILABLE|CARDF_POSTSTATUS,cah_cardflags(a1)
  3925.  bra.s   .was_goldie
  3926.  
  3927. .oldie:
  3928.  move.l  #status_int_code_v37,is_code(a0)
  3929.  move.b  #CARDF_IFAVAILABLE,cah_cardflags(a1)
  3930. .was_goldie:
  3931.  move.l  a0,cah_CardStatus(a1)
  3932.  
  3933.  lea     devicename(pc),a0
  3934.  move.l  a0,ln_name(a1)
  3935.  move.b  #20,ln_pri(a1)               ; high priority for I/O card
  3936.  
  3937.  jsr     _LVOOwnCard(a6)              ; own card (sets up interrupt vectors)
  3938.  tst.l   d0
  3939.  bne     .error
  3940.  
  3941.  or.b    #DDF_CARDIN|DDF_OWNED,dd_flags(a3)     ; card is inserted & owned by us
  3942.  
  3943. .owned:
  3944.  lea     dd_cardhandle(a3),a1
  3945.  lea     tuple(pc),a0
  3946.  moveq   #CISTPL_FUNC_ID,d1
  3947.  moveq   #40,d0
  3948.  move.l  dd_cardres(a3),a6
  3949.  jsr     _LVOCopyTuple(a6)            ; read function tuple
  3950.  tst.l   d0
  3951.  beq     .error
  3952.  
  3953.  lea     tuple(pc),a0
  3954.  move.b  2(a0),d0
  3955.  cmp.b   #CISTPL_FUNCID_NETWORK,d0    ; must be a network card!
  3956.  bne     .error
  3957.  
  3958.  lea     dd_cardhandle(a3),a1
  3959.  lea     tuple(pc),a0
  3960.  moveq   #CISTPL_CONF_MAP,d1
  3961.  moveq   #40,d0
  3962.  move.l  dd_cardres(a3),a6
  3963.  jsr     _LVOCopyTuple(a6)            ; read config map tuple
  3964.  tst.l   d0
  3965.  beq     .error
  3966.  
  3967.  lea     tuple(pc),a0
  3968.  move.b  2(a0),d0
  3969.  and.w   #$03,d0                      ; (number of address bytes)-1
  3970.  moveq   #0,d5
  3971.  
  3972. .getaddr:
  3973.  lsl.l   #8,d5
  3974.  move.b  4(a0,d0.w),d5                ; extract config register address
  3975.  subq.w  #1,d0
  3976.  bpl.s   .getaddr
  3977.  
  3978.  and.l   #$0001FFFF,d5                ; limit to attribute memory range
  3979.  lea     dd_cardhandle(a3),a1
  3980.  moveq   #CISTPL_CONFIG,d1
  3981.  moveq   #40,d0
  3982.  jsr     _LVOCopyTuple(a6)            ; read 1st config tuple
  3983.  tst.l   d0
  3984.  beq.s   .error
  3985.  
  3986.  lea     dd_cardhandle(a3),a1
  3987.  move.l  #CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO,d1
  3988.  jsr     _LVOCardMiscControl(a6)      ; enable card I/O functions
  3989.  lea     tuple(pc),a0
  3990.  move.b  2(a0),d0                     ; extract configuration ID value
  3991.  
  3992. .setconfig:
  3993.  and.b   #$3f,d0
  3994.  lea     AttrMem,a0
  3995.  add.l   d5,a0
  3996.  move.b  d0,(a0)                      ; put ID into card config register
  3997.  
  3998. .ok:
  3999.  bug     <"cnet: init_card: OK",10>
  4000.  moveq   #0,d0                        ; card is active, return OK
  4001.  
  4002. .done:
  4003.  movem.l (sp)+,d3-d6/a3/a6
  4004.  rts
  4005.  
  4006. .error:
  4007.  bug     <"cnet: init_card: failed!",10>
  4008.  moveq   #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
  4009.  bsr     DoEvent
  4010.  moveq   #-1,d0                       ; card not available, return error
  4011.  bra.s   .done
  4012.  
  4013.  
  4014.  
  4015. ;=================================================================
  4016. ;              initialise device data structures
  4017. ;=================================================================
  4018. ;
  4019. ;   init_device(device)
  4020. ;                 a1
  4021. ;
  4022. init_device:
  4023.  
  4024.  movem.l a3/a6,-(sp)
  4025.  move.l  a1,a3
  4026.  bset    #DDB_DEVINIT,dd_flags(a3)     ; already initialised ?
  4027.  bne     .done
  4028.  
  4029.  move.l  exec_base(pc),a6
  4030.  
  4031.  lea     dd_orphanlist(a3),a0          ; New MinList for orphan queue
  4032.  NEWLIST a0
  4033.  lea     dd_writelist(a3),a0           ; New MinList for write queue
  4034.  NEWLIST a0
  4035.  lea     dd_eventlist(a3),a0           ; New MinList for event queue
  4036.  NEWLIST a0
  4037.  lea     dd_bufmanlist(a3),a0          ; New MinList for bufman vectors
  4038.  NEWLIST a0
  4039.  lea     dd_tracklist(a3),a0           ; New MinList for tracking
  4040.  NEWLIST a0
  4041.  lea     dd_multicasts(a3),a0          ; New MinList for multicast filters
  4042.  NEWLIST a0
  4043.  
  4044.  lea     dd_multicastssema(a3),a0
  4045.  jsr     _LVOInitSemaphore(a6)
  4046.  
  4047.  lea     dd_rxint+ln_type(a3),a1
  4048.  lea     rxintname(pc),a0
  4049.  move.w  #(NT_INTERRUPT<<8)|16,(a1)+   ; priority 16
  4050.  move.l  a0,(a1)+                      ; set up rx swi
  4051.  lea     rxintcode(pc),a0
  4052.  move.l  a3,(a1)+
  4053.  move.l  a0,(a1)+
  4054.  
  4055.  lea     dd_txint+ln_type(a3),a1
  4056.  lea     txintname(pc),a0
  4057.  move.w  #(NT_INTERRUPT<<8)|0,(a1)+    ; priority 0
  4058.  move.l  a0,(a1)+                      ; set up tx swi
  4059.  lea     txintcode(pc),a0
  4060.  move.l  a3,(a1)+
  4061.  move.l  a0,(a1)+
  4062.  
  4063. .done:
  4064.  movem.l (sp)+,a3/a6
  4065.  rts
  4066.  
  4067.  
  4068.  
  4069. ;============================================================
  4070. ;             PCMCIA status change interrupt
  4071. ;============================================================
  4072. ;
  4073. ;   Occurs whenever a PCMCIA status line changes
  4074. ;
  4075. ;   eg. when the network card activates it's interrupt line
  4076. ;
  4077. ;
  4078. ;  entry:   d0 = status change(s)
  4079. ;           a1 = device
  4080. ;
  4081. ;  exit:    d0 must be preserved!
  4082. ;
  4083.  
  4084. STATINT MACRO
  4085.  
  4086.  movem.l d2-d6/a2-a4,-(sp)
  4087.  move.l  a1,a4                      ; a4 = device
  4088.  btst    #DDB_NICUP,dd_flags(a4)    ; is nic working ?
  4089.  beq     .done
  4090.  
  4091.  move.l  d0,d6                      ; d6 = status changes
  4092.  move.l  exec_base(pc),a6
  4093.  
  4094.  move.b  nic_cr,d5                  ; save old command
  4095.  delay
  4096.  move.b  #0,nic_imr                 ; prevent nic interrupts
  4097.  bra     .checkint
  4098.  
  4099. ; interrupt service loop    (d3 = interrupt status)
  4100.  
  4101. .intloop:
  4102.  btst    #DSIB_ROVRN,d3             ; Overwrite warning enable ?
  4103.  beq     .no_overflow
  4104. ; receiver ring buffer overflowed (eek!)
  4105.  addq.l  #1,dd_overflows(a4)
  4106.  delay
  4107.  move.b  #0,nic_rbcr0
  4108.  delay
  4109.  move.b  #0,nic_rbcr1               ; reset remote byte count
  4110.  delay
  4111.  move.b  #DSTC_LB0,nic_tcr
  4112.  delay                              ; monitor mode
  4113.  move.b  #DSRC_MON,nic_rcr
  4114.  delay
  4115.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; try to restart controller
  4116.  delay
  4117.  move.b  #DSRC_AB,nic_rcr
  4118.  delay                              ; normal rx mode
  4119.  move.b  #0,nic_tcr
  4120. .no_overflow:
  4121.  
  4122.  btst    #DSIB_RXE,d3               ; Receive error enable ?
  4123.  beq.s   .norxerr
  4124. ; bug     <"cnet: rx error",10>
  4125.  addq.l  #1,dd_devicestats+s2ds_baddata(a4) ; another bad rx packet ?
  4126.  delay
  4127.  move.b  nic_rsr,d0                 ; read rx status
  4128.  delay
  4129.  move.b  nic_cntr0,d0
  4130.  delay
  4131.  move.b  nic_cntr1,d0               ; read counters
  4132.  delay
  4133.  move.b  nic_cntr2,d0
  4134.  bra.s   .rx
  4135. .norxerr:
  4136.  
  4137.  btst    #DSIB_RX,d3                ; Packet received enable ?
  4138.  beq.s   .no_rx
  4139.  
  4140. ; new packet(s) arrived in receive ring buffer
  4141. .rx:
  4142.  and.b   #~(DSIM_OVWE|DSIM_RXEE|DSIM_PRXE),dd_imr(a4) ; ignore rx ints
  4143.  lea     dd_rxint(a4),a1
  4144.  jsr     _LVOCause(a6)              ; to copy packet(s) into waiting ioreq(s)
  4145. .no_rx:
  4146.  
  4147.  btst    #DSIB_TXE,d3               ; Transmit error enable ?
  4148.  bne.s   .tx
  4149.  btst    #DSIB_TX,d3                ; Packet transmitted enable ?
  4150.  beq     .no_tx
  4151.  
  4152. .tx:
  4153. ; a packet has just been transmitted
  4154.  moveq   #0,d0
  4155.  delay
  4156.  move.b  nic_ncr,d0                 ; read collision count
  4157.  bclr    #DDB_TX,dd_flags(a4)       ; buffer now free
  4158.  add.l   d0,dd_retries(a4)          ; increment retry count
  4159.  addq.l  #1,dd_devicestats+s2ds_packetssent(a4) ; count packets sent
  4160.  lea     dd_txint(a4),a1
  4161.  jsr     _LVOCause(a6)              ; to transmit next packet
  4162. .no_tx:
  4163.  
  4164.  btst    #DSIB_CTRS,d3              ; counter overflow ?
  4165.  beq.s   .nocounter
  4166.  
  4167. ; counter overflow
  4168.  delay
  4169.  move.b  nic_cntr0,d0
  4170.  delay
  4171.  move.b  nic_cntr1,d0               ; read counters
  4172.  delay
  4173.  move.b  nic_cntr2,d0
  4174. .nocounter:
  4175.  
  4176.  
  4177. .checkint:
  4178.  delay
  4179.  move.b  nic_isr,d3                 ; d3 = nic interrupt status
  4180.  delay
  4181.  move.b  d3,nic_isr                 ; clear current interrupt bit(s)
  4182.  and.b   dd_imr(a4),d3
  4183.  bne     .intloop                   ; any valid interrupts ?
  4184.  
  4185.  delay
  4186.  move.b  d5,nic_cr                  ; restore old command
  4187.  
  4188.  ENDM
  4189.  
  4190.  
  4191.  
  4192.  CNOP    0,4
  4193. status_int_code_v37:
  4194.  
  4195.  STATINT
  4196.  
  4197.  eor.b   #$2c,d6
  4198.  or.b    #$c0,d6
  4199.  move.b  d6,$da9000                 ; clear PCMCIA status change bits
  4200.  delay
  4201.  move.b  dd_imr(a4),nic_imr         ; enable nic interrupts
  4202.  moveq   #0,d0                      ; don't clear status bits coz we did
  4203.  
  4204. .done:
  4205.  movem.l (sp)+,d2-d6/a2-a4
  4206.  rts
  4207.  
  4208.  
  4209.  CNOP    0,4
  4210. status_int_code_v39:
  4211.  
  4212.  STATINT
  4213.  
  4214.  delay
  4215.  move.b  dd_imr(a4),nic_imr         ; enable nic interrupts
  4216.  move.l  d6,d0                      ; return original d0
  4217.  
  4218. .done:
  4219.  movem.l (sp)+,d2-d6/a2-a4
  4220.  rts
  4221.  
  4222.  
  4223.  
  4224. ;============================================================
  4225. ;             PCMCIA Card Inserted interrupt
  4226. ;============================================================
  4227. ;
  4228. ;   Occurs whenever a PCMCIA card is plugged in
  4229. ;
  4230. ; NOTE: card.resource has given us ownership of the card
  4231. ;
  4232. ;  entry: a1 = device
  4233. ;
  4234. ;  exit:  d0,d1,a0,a1,a5,a6 = scratch
  4235. ;
  4236. card_inserted_code:
  4237.  bug     <"cnet: PCMCIA card inserted",10>
  4238.  
  4239.  move.l  a1,a5
  4240.  
  4241.  tst.w   lib_opencnt(a5)               ; is someone interested about cards ?
  4242.  beq.s   .done
  4243.  
  4244.  or.b    #DDF_CARDIN|DDF_OWNED,dd_flags(a5) ; card is inserted & we own the card again
  4245.  
  4246.  bsr     init_card
  4247.  tst.l   d0                            ; attempt to init pcmcia card
  4248.  bne.s   .releasecard
  4249.  
  4250.  move.l  a5,a1
  4251.  bsr     init_nic                      ; attempt to start controller
  4252.  tst.l   d0
  4253.  beq.s   .good
  4254.  
  4255. .releasecard:
  4256.  lea     dd_cardhandle(a5),a1
  4257.  move.l  dd_cardres(a5),a6
  4258.  moveq   #0,d0
  4259.  jsr     _LVOReleaseCard(a6)           ; release foreign or bad card
  4260.  bclr    #DDB_OWNED,dd_flags(a5)
  4261.  bra.s   .done
  4262.  
  4263. .good:
  4264.  btst    #DDB_OFFLINE,dd_flags(a5)     ; has device been put offline ?
  4265.  bne.s   .done
  4266.  bset    #DDB_ONLINE,dd_flags(a5)      ; device is now online
  4267.  moveq   #S2EVENT_ONLINE,d0
  4268.  bra     DoEvent                       ; return ONLINE event
  4269.  
  4270. .done:
  4271.  rts
  4272.  
  4273.  
  4274.  
  4275. ;============================================================
  4276. ;             PCMCIA Card Removed interrupt
  4277. ;============================================================
  4278. ;
  4279. ;   Occurs whenever a PCMCIA card is unplugged
  4280. ;
  4281. ;  entry: a1 = device
  4282. ;
  4283. ;  exit:  d0,d1,a0,a1,a5,a6 = scratch
  4284. ;
  4285. card_removed_code:
  4286.  bug     <"cnet: PCMCIA card removed",10>
  4287.  
  4288.  move.l  a1,a5                          ; a5 = device
  4289. ;and.b   #~(DDF_OWNED|DDF_CARDIN|DDF_ONLINE|DDF_NICUP|DDF_CONFIGURED),dd_flags(a5)
  4290.  and.b   #~(DDF_OWNED|DDF_CARDIN|DDF_ONLINE|DDF_NICUP),dd_flags(a5)
  4291.  lea     dd_cardhandle(a5),a1
  4292.  move.l  dd_cardres(a5),a6
  4293.  moveq   #0,d0
  4294.  jsr     _LVOReleaseCard(a6)            ; release card
  4295.  
  4296.  moveq   #S2EVENT_OFFLINE,d0
  4297.  bra     DoEvent                        ; return OFFLINE event
  4298.  
  4299.  
  4300.  
  4301. ; debugging stuff...
  4302.  
  4303.  ifd     verbose
  4304. showpkt:
  4305.  movem.l a0-a1/d0-d2,-(sp)
  4306.  bug     <10>
  4307.  moveq   #0,d1
  4308.  
  4309. .rows:
  4310.  moveq   #15,d2
  4311.  lea     .string(pc),a0
  4312.  
  4313. .bytes:
  4314.  move.b  (a1)+,d1
  4315.  cmp.b   #' ',d1
  4316.  blo.s   .dot
  4317.  cmp.b   #'z',d1
  4318.  bhs.s   .dot
  4319.  move.b  d1,(a0)+
  4320.  bra.s   .ends
  4321. .dot:
  4322.  move.b  #'.',(a0)+
  4323. .ends:
  4324.  move.b  #0,(a0)
  4325.  bug     <"%02lx ">,d1
  4326.  subq.w  #1,d0
  4327.  beq.s   .end
  4328.  dbf     d2,.bytes
  4329.  bra.s   .shows
  4330.  
  4331. .endspc:
  4332.  bug     <"   ">
  4333. .end:
  4334.  dbf     d2,.endspc
  4335.  
  4336. .shows:
  4337.  bug     <"  %s",10>,#.string
  4338.  tst.w   d0
  4339.  bne.s   .rows
  4340.  
  4341.  bug     <10,10>
  4342.  movem.l (sp)+,a0-a1/d0-d2
  4343.  rts
  4344.  
  4345. .string:
  4346.  ds.b    16
  4347.  dc.b    0
  4348.  even
  4349.  endc
  4350.  
  4351.  
  4352. rxintname:
  4353.  dc.b "cnet rx softint",0
  4354. txintname:
  4355.  dc.b "cnet tx softint",0
  4356.  
  4357. cardname:
  4358.  dc.b "card.resource",0
  4359. timerdevname:
  4360.  dc.b "timer.device",0
  4361. utilityName:
  4362.  dc.b "utility.library",0
  4363.  
  4364. multiname:
  4365.  dc.b "bad multicasts",0
  4366. retryname:
  4367.  dc.b "retries",0
  4368.  
  4369. DeviceName:
  4370.  dc.b    "cnet.device",0
  4371.  
  4372.  
  4373.  dc.b    "$VER: "
  4374. IDString:
  4375.  dc.b    "cnet.device "
  4376.  VERSTR
  4377.  ifeq    __CPU-68000
  4378.  dc.b    " 68000+"
  4379.  else
  4380.  ifge    __CPU-68020
  4381.  dc.b    " 68020+"
  4382.  endc
  4383.  endc
  4384.  ifd     turboio
  4385.  dc.b    "/turboio"
  4386.  endc
  4387.  ifd     debug
  4388.  dc.b    "/debug"
  4389.  endc
  4390.  dc.b    " by Harry ",34,"Piru",34," Sintonen",10,0
  4391.  
  4392.  
  4393. ; devicequery block
  4394.  
  4395.  CNOP 0,2
  4396. size_supplied:
  4397.  dc.l    S2DQ_SIZE            ; bytes supplied (size of this block)
  4398.  dc.l    0                    ; this is type 0
  4399.  dc.l    0                    ; this document is level 0
  4400.  dc.w    ETHER_ADDR_SIZE*8    ; address size in bits
  4401.  dc.l    ETHERPKT_SIZE        ; maximum packet data size
  4402.  dc.l    10000000             ; line rate (10 Megabits/sec)
  4403.  dc.l    S2WIRETYPE_ETHERNET  ; what the wire is
  4404.  
  4405.  
  4406. ; default station address to use if the card won't give it to us.
  4407.  
  4408.  CNOP 0,2
  4409. default_address:
  4410.  dc.b $00,$00,$12,$34,$56,$78 ; replace this with your card's address!
  4411.  
  4412.  
  4413. ;--------------------------------------------------------
  4414. ;                      Global data
  4415. ;--------------------------------------------------------
  4416.  
  4417.  CNOP 0,4
  4418.  
  4419. exec_base:     dc.l 0   ; local copy of execbase
  4420.  
  4421. utility_base:  dc.l 0   ; for walking taglist
  4422.  
  4423. me_myself:     dc.l 0   ; pointer to this device
  4424.  
  4425. timerdevice:   dc.l 0   ; timer device base
  4426.  
  4427. mcastaddr:     ds.b 8   ; multicast address filter bitfield
  4428.  
  4429.  
  4430. ; ---- Timer I/O Request ----
  4431.  CNOP 0,2
  4432. timereq:
  4433.    dc.l 0           ; ln_head  }         }
  4434.    dc.l 0           ; ln_pred  }         }
  4435.    dc.b 0           ; ln_type  } mp_node }
  4436.    dc.b 0           ; ln_pri   }         } io_message
  4437.    dc.l 0           ; ln_name  }         }
  4438.    dc.l 0           ; mn_replyport       }
  4439.    dc.w 0           ; mn_length          }
  4440.    dc.l 0           ;  io_device
  4441.    dc.l 0           ;  io_unit
  4442.    dc.w 0           ;  io_command
  4443.    dc.b 0           ;  io_flags
  4444.    dc.b 0           ;  io_error
  4445.    dc.l 0           ;  tv_secs
  4446.    dc.l 0           ;  tv_micros
  4447.  
  4448.  
  4449. tuple:         ds.b 48  ; PCMCIA tuple buffer
  4450.  
  4451.  
  4452. ; linked with phxlnk so no need for separate bss hunk!
  4453. ; section buffers,bss
  4454.  
  4455.  CNOP 0,8
  4456. rx_header:
  4457.  ds.b  prhdr_sizeof
  4458. rxbuffer:
  4459.  ds.b  PKTBUF_SIZE-prhdr_sizeof      ; received packet buffer
  4460.  
  4461.  CNOP 0,8
  4462. txbuffer:
  4463.  ds.b  PKTBUF_SIZE      ; transmit packet buffer
  4464.  
  4465.  
  4466.  CNOP 0,2
  4467. Endcode:
  4468.